1/*
2 * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24#include "precompiled.hpp"
25#include "memory/resourceArea.hpp"
26#include "runtime/os.hpp"
27#include "utilities/ostream.hpp"
28#include "unittest.hpp"
29
30static size_t small_page_size() {
31 return os::vm_page_size();
32}
33
34static size_t large_page_size() {
35 const size_t large_page_size_example = 4 * M;
36 return os::page_size_for_region_aligned(large_page_size_example, 1);
37}
38
39TEST_VM(os, page_size_for_region) {
40 size_t large_page_example = 4 * M;
41 size_t large_page = os::page_size_for_region_aligned(large_page_example, 1);
42
43 size_t small_page = os::vm_page_size();
44 if (large_page > small_page) {
45 size_t num_small_in_large = large_page / small_page;
46 size_t page = os::page_size_for_region_aligned(large_page, num_small_in_large);
47 ASSERT_EQ(page, small_page) << "Did not get a small page";
48 }
49}
50
51TEST_VM(os, page_size_for_region_aligned) {
52 if (UseLargePages) {
53 const size_t small_page = small_page_size();
54 const size_t large_page = large_page_size();
55
56 if (large_page > small_page) {
57 size_t num_small_pages_in_large = large_page / small_page;
58 size_t page = os::page_size_for_region_aligned(large_page, num_small_pages_in_large);
59
60 ASSERT_EQ(page, small_page);
61 }
62 }
63}
64
65TEST_VM(os, page_size_for_region_alignment) {
66 if (UseLargePages) {
67 const size_t small_page = small_page_size();
68 const size_t large_page = large_page_size();
69 if (large_page > small_page) {
70 const size_t unaligned_region = large_page + 17;
71 size_t page = os::page_size_for_region_aligned(unaligned_region, 1);
72 ASSERT_EQ(page, small_page);
73
74 const size_t num_pages = 5;
75 const size_t aligned_region = large_page * num_pages;
76 page = os::page_size_for_region_aligned(aligned_region, num_pages);
77 ASSERT_EQ(page, large_page);
78 }
79 }
80}
81
82TEST_VM(os, page_size_for_region_unaligned) {
83 if (UseLargePages) {
84 // Given exact page size, should return that page size.
85 for (size_t i = 0; os::_page_sizes[i] != 0; i++) {
86 size_t expected = os::_page_sizes[i];
87 size_t actual = os::page_size_for_region_unaligned(expected, 1);
88 ASSERT_EQ(expected, actual);
89 }
90
91 // Given slightly larger size than a page size, return the page size.
92 for (size_t i = 0; os::_page_sizes[i] != 0; i++) {
93 size_t expected = os::_page_sizes[i];
94 size_t actual = os::page_size_for_region_unaligned(expected + 17, 1);
95 ASSERT_EQ(expected, actual);
96 }
97
98 // Given a slightly smaller size than a page size,
99 // return the next smaller page size.
100 if (os::_page_sizes[1] > os::_page_sizes[0]) {
101 size_t expected = os::_page_sizes[0];
102 size_t actual = os::page_size_for_region_unaligned(os::_page_sizes[1] - 17, 1);
103 ASSERT_EQ(actual, expected);
104 }
105
106 // Return small page size for values less than a small page.
107 size_t small_page = small_page_size();
108 size_t actual = os::page_size_for_region_unaligned(small_page - 17, 1);
109 ASSERT_EQ(small_page, actual);
110 }
111}
112
113TEST(os, test_random) {
114 const double m = 2147483647;
115 double mean = 0.0, variance = 0.0, t;
116 const int reps = 10000;
117 unsigned int seed = 1;
118
119 // tty->print_cr("seed %ld for %ld repeats...", seed, reps);
120 os::init_random(seed);
121 int num;
122 for (int k = 0; k < reps; k++) {
123 num = os::random();
124 double u = (double)num / m;
125 ASSERT_TRUE(u >= 0.0 && u <= 1.0) << "bad random number!";
126
127 // calculate mean and variance of the random sequence
128 mean += u;
129 variance += (u*u);
130 }
131 mean /= reps;
132 variance /= (reps - 1);
133
134 ASSERT_EQ(num, 1043618065) << "bad seed";
135 // tty->print_cr("mean of the 1st 10000 numbers: %f", mean);
136 int intmean = mean*100;
137 ASSERT_EQ(intmean, 50);
138 // tty->print_cr("variance of the 1st 10000 numbers: %f", variance);
139 int intvariance = variance*100;
140 ASSERT_EQ(intvariance, 33);
141 const double eps = 0.0001;
142 t = fabsd(mean - 0.5018);
143 ASSERT_LT(t, eps) << "bad mean";
144 t = (variance - 0.3355) < 0.0 ? -(variance - 0.3355) : variance - 0.3355;
145 ASSERT_LT(t, eps) << "bad variance";
146}
147
148
149#ifdef ASSERT
150TEST_VM_ASSERT_MSG(os, page_size_for_region_with_zero_min_pages, "sanity") {
151 size_t region_size = 16 * os::vm_page_size();
152 os::page_size_for_region_aligned(region_size, 0); // should assert
153}
154#endif
155
156static void do_test_print_hex_dump(address addr, size_t len, int unitsize, const char* expected) {
157 char buf[256];
158 buf[0] = '\0';
159 stringStream ss(buf, sizeof(buf));
160 os::print_hex_dump(&ss, addr, addr + len, unitsize);
161// tty->print_cr("expected: %s", expected);
162// tty->print_cr("result: %s", buf);
163 ASSERT_NE(strstr(buf, expected), (char*)NULL);
164}
165
166TEST_VM(os, test_print_hex_dump) {
167 const char* pattern [4] = {
168#ifdef VM_LITTLE_ENDIAN
169 "00 01 02 03 04 05 06 07",
170 "0100 0302 0504 0706",
171 "03020100 07060504",
172 "0706050403020100"
173#else
174 "00 01 02 03 04 05 06 07",
175 "0001 0203 0405 0607",
176 "00010203 04050607",
177 "0001020304050607"
178#endif
179 };
180
181 const char* pattern_not_readable [4] = {
182 "?? ?? ?? ?? ?? ?? ?? ??",
183 "???? ???? ???? ????",
184 "???????? ????????",
185 "????????????????"
186 };
187
188 // On AIX, zero page is readable.
189 address unreadable =
190#ifdef AIX
191 (address) 0xFFFFFFFFFFFF0000ULL;
192#else
193 (address) 0
194#endif
195 ;
196
197 ResourceMark rm;
198 char buf[64];
199 stringStream ss(buf, sizeof(buf));
200 outputStream* out = &ss;
201// outputStream* out = tty; // enable for printout
202
203 // Test dumping unreadable memory
204 // Exclude test for Windows for now, since it needs SEH handling to work which cannot be
205 // guaranteed when we call directly into VM code. (see JDK-8220220)
206#ifndef _WIN32
207 do_test_print_hex_dump(unreadable, 100, 1, pattern_not_readable[0]);
208 do_test_print_hex_dump(unreadable, 100, 2, pattern_not_readable[1]);
209 do_test_print_hex_dump(unreadable, 100, 4, pattern_not_readable[2]);
210 do_test_print_hex_dump(unreadable, 100, 8, pattern_not_readable[3]);
211#endif
212
213 // Test dumping readable memory
214 address arr = (address)os::malloc(100, mtInternal);
215 for (int c = 0; c < 100; c++) {
216 arr[c] = c;
217 }
218
219 // properly aligned
220 do_test_print_hex_dump(arr, 100, 1, pattern[0]);
221 do_test_print_hex_dump(arr, 100, 2, pattern[1]);
222 do_test_print_hex_dump(arr, 100, 4, pattern[2]);
223 do_test_print_hex_dump(arr, 100, 8, pattern[3]);
224
225 // Not properly aligned. Should automatically down-align by unitsize
226 do_test_print_hex_dump(arr + 1, 100, 2, pattern[1]);
227 do_test_print_hex_dump(arr + 1, 100, 4, pattern[2]);
228 do_test_print_hex_dump(arr + 1, 100, 8, pattern[3]);
229
230 os::free(arr);
231}
232
233//////////////////////////////////////////////////////////////////////////////
234// Test os::vsnprintf and friends.
235
236static void check_snprintf_result(int expected, size_t limit, int actual, bool expect_count) {
237 if (expect_count || ((size_t)expected < limit)) {
238 ASSERT_EQ(expected, actual);
239 } else {
240 ASSERT_GT(0, actual);
241 }
242}
243
244// PrintFn is expected to be int (*)(char*, size_t, const char*, ...).
245// But jio_snprintf is a C-linkage function with that signature, which
246// has a different type on some platforms (like Solaris).
247template<typename PrintFn>
248static void test_snprintf(PrintFn pf, bool expect_count) {
249 const char expected[] = "abcdefghijklmnopqrstuvwxyz";
250 const int expected_len = sizeof(expected) - 1;
251 const size_t padding_size = 10;
252 char buffer[2 * (sizeof(expected) + padding_size)];
253 char check_buffer[sizeof(buffer)];
254 const char check_char = '1'; // Something not in expected.
255 memset(check_buffer, check_char, sizeof(check_buffer));
256 const size_t sizes_to_test[] = {
257 sizeof(buffer) - padding_size, // Fits, with plenty of space to spare.
258 sizeof(buffer)/2, // Fits, with space to spare.
259 sizeof(buffer)/4, // Doesn't fit.
260 sizeof(expected) + padding_size + 1, // Fits, with a little room to spare
261 sizeof(expected) + padding_size, // Fits exactly.
262 sizeof(expected) + padding_size - 1, // Doesn't quite fit.
263 2, // One char + terminating NUL.
264 1, // Only space for terminating NUL.
265 0 }; // No space at all.
266 for (unsigned i = 0; i < ARRAY_SIZE(sizes_to_test); ++i) {
267 memset(buffer, check_char, sizeof(buffer)); // To catch stray writes.
268 size_t test_size = sizes_to_test[i];
269 ResourceMark rm;
270 stringStream s;
271 s.print("test_size: " SIZE_FORMAT, test_size);
272 SCOPED_TRACE(s.as_string());
273 size_t prefix_size = padding_size;
274 guarantee(test_size <= (sizeof(buffer) - prefix_size), "invariant");
275 size_t write_size = MIN2(sizeof(expected), test_size);
276 size_t suffix_size = sizeof(buffer) - prefix_size - write_size;
277 char* write_start = buffer + prefix_size;
278 char* write_end = write_start + write_size;
279
280 int result = pf(write_start, test_size, "%s", expected);
281
282 check_snprintf_result(expected_len, test_size, result, expect_count);
283
284 // Verify expected output.
285 if (test_size > 0) {
286 ASSERT_EQ(0, strncmp(write_start, expected, write_size - 1));
287 // Verify terminating NUL of output.
288 ASSERT_EQ('\0', write_start[write_size - 1]);
289 } else {
290 guarantee(test_size == 0, "invariant");
291 guarantee(write_size == 0, "invariant");
292 guarantee(prefix_size + suffix_size == sizeof(buffer), "invariant");
293 guarantee(write_start == write_end, "invariant");
294 }
295
296 // Verify no scribbling on prefix or suffix.
297 ASSERT_EQ(0, strncmp(buffer, check_buffer, prefix_size));
298 ASSERT_EQ(0, strncmp(write_end, check_buffer, suffix_size));
299 }
300
301 // Special case of 0-length buffer with empty (except for terminator) output.
302 check_snprintf_result(0, 0, pf(NULL, 0, "%s", ""), expect_count);
303 check_snprintf_result(0, 0, pf(NULL, 0, ""), expect_count);
304}
305
306// This is probably equivalent to os::snprintf, but we're being
307// explicit about what we're testing here.
308static int vsnprintf_wrapper(char* buf, size_t len, const char* fmt, ...) {
309 va_list args;
310 va_start(args, fmt);
311 int result = os::vsnprintf(buf, len, fmt, args);
312 va_end(args);
313 return result;
314}
315
316TEST_VM(os, vsnprintf) {
317 test_snprintf(vsnprintf_wrapper, true);
318}
319
320TEST_VM(os, snprintf) {
321 test_snprintf(os::snprintf, true);
322}
323
324// These are declared in jvm.h; test here, with related functions.
325extern "C" {
326int jio_vsnprintf(char*, size_t, const char*, va_list);
327int jio_snprintf(char*, size_t, const char*, ...);
328}
329
330// This is probably equivalent to jio_snprintf, but we're being
331// explicit about what we're testing here.
332static int jio_vsnprintf_wrapper(char* buf, size_t len, const char* fmt, ...) {
333 va_list args;
334 va_start(args, fmt);
335 int result = jio_vsnprintf(buf, len, fmt, args);
336 va_end(args);
337 return result;
338}
339
340TEST_VM(os, jio_vsnprintf) {
341 test_snprintf(jio_vsnprintf_wrapper, false);
342}
343
344TEST_VM(os, jio_snprintf) {
345 test_snprintf(jio_snprintf, false);
346}
347