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 30 static size_t small_page_size() { 31 return os::vm_page_size(); 32 } 33 34 static 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 39 TEST_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 51 TEST_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 65 TEST_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 82 TEST_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 113 TEST(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 150 TEST_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 156 ////////////////////////////////////////////////////////////////////////////// 157 // Test os::vsnprintf and friends. 158 159 static void check_snprintf_result(int expected, size_t limit, int actual, bool expect_count) { 160 if (expect_count || ((size_t)expected < limit)) { 161 ASSERT_EQ(expected, actual); 162 } else { 163 ASSERT_GT(0, actual); 164 } 165 } 166 167 // PrintFn is expected to be int (*)(char*, size_t, const char*, ...). 168 // But jio_snprintf is a C-linkage function with that signature, which 169 // has a different type on some platforms (like Solaris). 170 template<typename PrintFn> 171 static void test_snprintf(PrintFn pf, bool expect_count) { 172 const char expected[] = "abcdefghijklmnopqrstuvwxyz"; 173 const int expected_len = sizeof(expected) - 1; 174 const size_t padding_size = 10; 175 char buffer[2 * (sizeof(expected) + padding_size)]; 176 char check_buffer[sizeof(buffer)]; 177 const char check_char = '1'; // Something not in expected. 178 memset(check_buffer, check_char, sizeof(check_buffer)); 179 const size_t sizes_to_test[] = { 180 sizeof(buffer) - padding_size, // Fits, with plenty of space to spare. 181 sizeof(buffer)/2, // Fits, with space to spare. 182 sizeof(buffer)/4, // Doesn't fit. 183 sizeof(expected) + padding_size + 1, // Fits, with a little room to spare 184 sizeof(expected) + padding_size, // Fits exactly. 185 sizeof(expected) + padding_size - 1, // Doesn't quite fit. 186 2, // One char + terminating NUL. 187 1}; // Only space for terminating NUL. 188 for (unsigned i = 0; i < ARRAY_SIZE(sizes_to_test); ++i) { 189 memset(buffer, check_char, sizeof(buffer)); // To catch stray writes. 190 size_t test_size = sizes_to_test[i]; 191 ResourceMark rm; 192 stringStream s; 193 s.print("test_size: " SIZE_FORMAT, test_size); 194 SCOPED_TRACE(s.as_string()); 195 size_t prefix_size = padding_size; 196 guarantee(test_size <= (sizeof(buffer) - prefix_size), "invariant"); 197 size_t write_size = MIN2(sizeof(expected), test_size); 198 size_t suffix_size = sizeof(buffer) - prefix_size - write_size; 199 char* write_start = buffer + prefix_size; 200 char* write_end = write_start + write_size; 201 202 int result = pf(write_start, test_size, "%s", expected); 203 204 check_snprintf_result(expected_len, test_size, result, expect_count); 205 206 // Verify expected output. 207 ASSERT_EQ(0, strncmp(write_start, expected, write_size - 1)); 208 // Verify terminating NUL of output. 209 ASSERT_EQ('\0', write_start[write_size - 1]); 210 211 // Verify no scribbling on prefix or suffix. 212 ASSERT_EQ(0, strncmp(buffer, check_buffer, prefix_size)); 213 ASSERT_EQ(0, strncmp(write_end, check_buffer, suffix_size)); 214 } 215 } 216 217 // This is probably equivalent to os::snprintf, but we're being 218 // explicit about what we're testing here. 219 static int vsnprintf_wrapper(char* buf, size_t len, const char* fmt, ...) { 220 va_list args; 221 va_start(args, fmt); 222 int result = os::vsnprintf(buf, len, fmt, args); 223 va_end(args); 224 return result; 225 } 226 227 TEST(os, vsnprintf) { 228 test_snprintf(vsnprintf_wrapper, true); 229 } 230 231 TEST(os, snprintf) { 232 test_snprintf(os::snprintf, true); 233 } 234 235 // These are declared in jvm.h; test here, with related functions. 236 extern "C" { 237 int jio_vsnprintf(char*, size_t, const char*, va_list); 238 int jio_snprintf(char*, size_t, const char*, ...); 239 } 240 241 // This is probably equivalent to jio_snprintf, but we're being 242 // explicit about what we're testing here. 243 static int jio_vsnprintf_wrapper(char* buf, size_t len, const char* fmt, ...) { 244 va_list args; 245 va_start(args, fmt); 246 int result = jio_vsnprintf(buf, len, fmt, args); 247 va_end(args); 248 return result; 249 } 250 251 TEST(os, jio_vsnprintf) { 252 test_snprintf(jio_vsnprintf_wrapper, false); 253 } 254 255 TEST(os, jio_snprintf) { 256 test_snprintf(jio_snprintf, false); 257 }