1 /* 2 * Copyright (c) 2016, 2017, 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 "runtime/os.hpp" 26 #include "unittest.hpp" 27 #include "utilities/decoder.hpp" 28 29 static size_t small_page_size() { 30 return os::vm_page_size(); 31 } 32 33 static size_t large_page_size() { 34 const size_t large_page_size_example = 4 * M; 35 return os::page_size_for_region_aligned(large_page_size_example, 1); 36 } 37 38 TEST_VM(os, page_size_for_region) { 39 size_t large_page_example = 4 * M; 40 size_t large_page = os::page_size_for_region_aligned(large_page_example, 1); 41 42 size_t small_page = os::vm_page_size(); 43 if (large_page > small_page) { 44 size_t num_small_in_large = large_page / small_page; 45 size_t page = os::page_size_for_region_aligned(large_page, num_small_in_large); 46 ASSERT_EQ(page, small_page) << "Did not get a small page"; 47 } 48 } 49 50 TEST_VM(os, page_size_for_region_aligned) { 51 if (UseLargePages) { 52 const size_t small_page = small_page_size(); 53 const size_t large_page = large_page_size(); 54 55 if (large_page > small_page) { 56 size_t num_small_pages_in_large = large_page / small_page; 57 size_t page = os::page_size_for_region_aligned(large_page, num_small_pages_in_large); 58 59 ASSERT_EQ(page, small_page); 60 } 61 } 62 } 63 64 TEST_VM(os, page_size_for_region_alignment) { 65 if (UseLargePages) { 66 const size_t small_page = small_page_size(); 67 const size_t large_page = large_page_size(); 68 if (large_page > small_page) { 69 const size_t unaligned_region = large_page + 17; 70 size_t page = os::page_size_for_region_aligned(unaligned_region, 1); 71 ASSERT_EQ(page, small_page); 72 73 const size_t num_pages = 5; 74 const size_t aligned_region = large_page * num_pages; 75 page = os::page_size_for_region_aligned(aligned_region, num_pages); 76 ASSERT_EQ(page, large_page); 77 } 78 } 79 } 80 81 TEST_VM(os, page_size_for_region_unaligned) { 82 if (UseLargePages) { 83 // Given exact page size, should return that page size. 84 for (size_t i = 0; os::_page_sizes[i] != 0; i++) { 85 size_t expected = os::_page_sizes[i]; 86 size_t actual = os::page_size_for_region_unaligned(expected, 1); 87 ASSERT_EQ(expected, actual); 88 } 89 90 // Given slightly larger size than a page size, return the page size. 91 for (size_t i = 0; os::_page_sizes[i] != 0; i++) { 92 size_t expected = os::_page_sizes[i]; 93 size_t actual = os::page_size_for_region_unaligned(expected + 17, 1); 94 ASSERT_EQ(expected, actual); 95 } 96 97 // Given a slightly smaller size than a page size, 98 // return the next smaller page size. 99 if (os::_page_sizes[1] > os::_page_sizes[0]) { 100 size_t expected = os::_page_sizes[0]; 101 size_t actual = os::page_size_for_region_unaligned(os::_page_sizes[1] - 17, 1); 102 ASSERT_EQ(actual, expected); 103 } 104 105 // Return small page size for values less than a small page. 106 size_t small_page = small_page_size(); 107 size_t actual = os::page_size_for_region_unaligned(small_page - 17, 1); 108 ASSERT_EQ(small_page, actual); 109 } 110 } 111 112 TEST(os, test_random) { 113 const double m = 2147483647; 114 double mean = 0.0, variance = 0.0, t; 115 const int reps = 10000; 116 unsigned int seed = 1; 117 118 // tty->print_cr("seed %ld for %ld repeats...", seed, reps); 119 os::init_random(seed); 120 int num; 121 for (int k = 0; k < reps; k++) { 122 num = os::random(); 123 double u = (double)num / m; 124 ASSERT_TRUE(u >= 0.0 && u <= 1.0) << "bad random number!"; 125 126 // calculate mean and variance of the random sequence 127 mean += u; 128 variance += (u*u); 129 } 130 mean /= reps; 131 variance /= (reps - 1); 132 133 ASSERT_EQ(num, 1043618065) << "bad seed"; 134 // tty->print_cr("mean of the 1st 10000 numbers: %f", mean); 135 int intmean = mean*100; 136 ASSERT_EQ(intmean, 50); 137 // tty->print_cr("variance of the 1st 10000 numbers: %f", variance); 138 int intvariance = variance*100; 139 ASSERT_EQ(intvariance, 33); 140 const double eps = 0.0001; 141 t = fabsd(mean - 0.5018); 142 ASSERT_LT(t, eps) << "bad mean"; 143 t = (variance - 0.3355) < 0.0 ? -(variance - 0.3355) : variance - 0.3355; 144 ASSERT_LT(t, eps) << "bad variance"; 145 } 146 147 #ifdef _WIN32 148 TEST(os, dll_addr_to_function_valid) { 149 char buf[128] = ""; 150 int offset = -1; 151 address valid_function_pointer = (address) JNI_CreateJavaVM; 152 ASSERT_TRUE(os::dll_address_to_function_name(valid_function_pointer, 153 buf, sizeof(buf), &offset, true) == true); 154 ASSERT_TRUE(strstr(buf, "JNI_CreateJavaVM") != NULL); 155 ASSERT_TRUE(offset >= 0); 156 } 157 158 // Test that handing down a too-small output buffer will truncate the output 159 // string correctly but cause no harm otherwise. 160 TEST(os, dll_addr_to_function_valid_truncated) { 161 char buf[128] = ""; 162 int offset = -1; 163 memset(buf, 'X', sizeof(buf)); 164 address valid_function_pointer = (address) JNI_CreateJavaVM; 165 ASSERT_TRUE(os::dll_address_to_function_name(valid_function_pointer, 166 buf, 10, &offset, true) == true); 167 ASSERT_TRUE(buf[10 - 1] == '\0'); 168 ASSERT_TRUE(buf[10] == 'X'); 169 // Note: compare the first (sizeof buf - 2) bytes only because Windows decoder 170 // (actually UndecorateSymbolName()) seems to have a bug where it uses one byte less than 171 // the buffer would offer. 172 ASSERT_TRUE(strncmp(buf, "JNI_Crea", 8) == 0); 173 ASSERT_TRUE(offset >= 0); 174 } 175 176 // Test that handing down invalid addresses will cause no harm and output buffer 177 // and offset will contain "" and -1, respectively. 178 TEST(os, dll_addr_to_function_invalid) { 179 char buf[128]; 180 int offset; 181 address invalid_function_pointers[] = { NULL, (address)1, (address)&offset }; 182 183 for (int i = 0; 184 i < sizeof(invalid_function_pointers) / sizeof(address); 185 i ++) 186 { 187 address addr = invalid_function_pointers[i]; 188 strcpy(buf, "blabla"); 189 offset = 12; 190 ASSERT_TRUE(os::dll_address_to_function_name(addr, buf, sizeof(buf), 191 &offset, true) == false); 192 ASSERT_TRUE(buf[0] == '\0'); 193 ASSERT_TRUE(offset == -1); 194 } 195 } 196 197 TEST(os, decoder_get_source_info_valid) { 198 char buf[128] = ""; 199 int line = -1; 200 address valid_function_pointer = (address) JNI_CreateJavaVM; 201 ASSERT_TRUE(Decoder::get_source_info(valid_function_pointer, buf, sizeof(buf), &line) == true); 202 ASSERT_TRUE(strcmp(buf, "jni.cpp") == 0); 203 ASSERT_TRUE(line >= 0); 204 } 205 206 // Test that handing down a too-small output buffer will truncate the output 207 // string correctly but cause no harm otherwise. 208 TEST(os, decoder_get_source_info_valid_truncated) { 209 char buf[128] = ""; 210 int line = -1; 211 memset(buf, 'X', sizeof(buf)); 212 address valid_function_pointer = (address) JNI_CreateJavaVM; 213 ASSERT_TRUE(Decoder::get_source_info(valid_function_pointer, buf, 7, &line) == true); 214 ASSERT_TRUE(buf[7 - 1] == '\0'); 215 ASSERT_TRUE(buf[7] == 'X'); 216 ASSERT_TRUE(strcmp(buf, "jni.cp") == 0); 217 ASSERT_TRUE(line > 0); 218 } 219 220 // Test that handing down invalid addresses will cause no harm and output buffer 221 // and line will contain "" and -1, respectively. 222 TEST(os, decoder_get_source_info_invalid) { 223 char buf[128] = ""; 224 int line = -1; 225 address invalid_function_pointers[] = { NULL, (address)1, (address)&line }; 226 227 for (int i = 0; 228 i < sizeof(invalid_function_pointers) / sizeof(address); 229 i ++) 230 { 231 address addr = invalid_function_pointers[i]; 232 // We should fail but not crash 233 strcpy(buf, "blabla"); 234 line = 12; 235 ASSERT_TRUE(Decoder::get_source_info(addr, buf, sizeof(buf), &line) == false); 236 // buffer should contain "", offset should contain -1 237 ASSERT_TRUE(buf[0] == '\0'); 238 ASSERT_TRUE(line == -1); 239 } 240 } 241 242 #ifdef PLATFORM_PRINT_NATIVE_STACK 243 TEST(os, platform_print_native_stack) { 244 bufferedStream bs; 245 // Note: scratch buffer argument to os::platform_print_native_stack is not 246 // optional! 247 char scratch_buffer [255]; 248 for (int i = 0; i < 3; i ++) { 249 ASSERT_TRUE(os::platform_print_native_stack(&bs, NULL, scratch_buffer, 250 sizeof(scratch_buffer))); 251 ASSERT_TRUE(bs.size() > 0); 252 // This may depend on debug information files being generated and available 253 // (e.g. not zipped). 254 ASSERT_TRUE(::strstr(bs.base(), "platform_print_native_stack") != NULL); 255 #ifdef _WIN32 256 // We have source information on Windows. 257 ASSERT_TRUE(::strstr(bs.base(), "os_windows_x86.cpp") != NULL); 258 #endif 259 } 260 } 261 #endif 262 #endif 263 264 #ifdef ASSERT 265 TEST_VM_ASSERT_MSG(os, page_size_for_region_with_zero_min_pages, "sanity") { 266 size_t region_size = 16 * os::vm_page_size(); 267 os::page_size_for_region_aligned(region_size, 0); // should assert 268 } 269 #endif