/* * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/
// test tries to allocate memory in a single contiguous memory block at a particular address. // The test first tries to find a good approximate address to allocate at by using the same // method to allocate some memory at any address. The test then tries to allocate memory in // the vicinity (not directly after it to avoid possible by-chance use of that location) // This is of course only some dodgy assumption, there is no guarantee that the vicinity of // the previously allocated memory is available for allocation. The only actual failure // that is reported is when the test tries to allocate at a particular location but gets a // different valid one. A NULL return value at this point is not considered an error but may // be legitimate. void TestReserveMemorySpecial_test() { if (!UseLargePages) { return;
}
// set globals to make sure we hit the correct code path
AutoSaveRestore<bool> FLAG_GUARD(UseLargePagesIndividualAllocation);
AutoSaveRestore<bool> FLAG_GUARD(UseNUMAInterleaving);
FLAG_SET_CMDLINE(UseLargePagesIndividualAllocation, false);
FLAG_SET_CMDLINE(UseNUMAInterleaving, false);
const size_t large_allocation_size = os::large_page_size() * 4; char* result = os::reserve_memory_special(large_allocation_size, os::large_page_size(), os::large_page_size(), NULL, false); if (result == NULL) { // failed to allocate memory, skipping the test return;
}
MemoryReleaser m1(result, large_allocation_size);
// Reserve another page within the recently allocated memory area. This should fail const size_t expected_allocation_size = os::large_page_size(); char* expected_location = result + os::large_page_size(); char* actual_location = os::reserve_memory_special(expected_allocation_size, os::large_page_size(), os::large_page_size(), expected_location, false);
EXPECT_TRUE(actual_location == NULL) << "Should not be allowed to reserve within present reservation";
// Instead try reserving after the first reservation.
expected_location = result + large_allocation_size;
actual_location = os::reserve_memory_special(expected_allocation_size, os::large_page_size(), os::large_page_size(), expected_location, false);
EXPECT_TRUE(actual_location != NULL) << "Unexpected reservation failure, can’t verify correct location";
EXPECT_TRUE(actual_location == expected_location) << "Reservation must be at requested location";
MemoryReleaser m2(actual_location, os::large_page_size());
// Now try to do a reservation with a larger alignment. const size_t alignment = os::large_page_size() * 2; const size_t new_large_size = alignment * 4; char* aligned_request = os::reserve_memory_special(new_large_size, alignment, os::large_page_size(), NULL, false);
EXPECT_TRUE(aligned_request != NULL) << "Unexpected reservation failure, can’t verify correct alignment";
EXPECT_TRUE(is_aligned(aligned_request, alignment)) << "Returned address must be aligned";
MemoryReleaser m3(aligned_request, new_large_size);
}
// The types of path modifications we randomly apply to a path. They should not change the file designated by the path. enum ModsFilter {
Allow_None = 0, // No modifications
Allow_Sep_Mods = 1, // Replace '\\' by any sequence of '/' or '\\' or at least length 1.
Allow_Dot_Path = 2, // Add /. segments at random positions
Allow_Dot_Dot_Path = 4, // Add /../<correct-dir> segments at random positions.
Allow_All = Allow_Sep_Mods | Allow_Dot_Path | Allow_Dot_Dot_Path
};
// The mode in which to run. enum Mode {
TEST, // Runs the test. This is the normal modus.
EXAMPLES, // Runs example which document the behaviour of the Windows system calls.
BENCH // Runs a small benchmark which tries to show the costs of using the *W variants/_wfullpath.
};
// Parameters of the test. static ModsFilter mods_filter = Allow_All; staticint mods_per_path = 50; // The number of variants of a path we try. static Mode mode = TEST;
// Utility methods staticvoid get_current_dir_w(wchar_t* path, size_t size) {
DWORD count = GetCurrentDirectoryW((DWORD) size, path);
EXPECT_GT((int) count, 0) << "Failed to get current directory: " << GetLastError();
EXPECT_LT((size_t) count, size) << "Buffer too small for current directory: " << size;
}
// If the directory cannot be deleted directly, a file in it might be kept // open by a virus scanner. Try a few times, since this should be temporary. for (int i = 0; i <= retry_count; ++i) { BOOL result = RemoveDirectoryW(abs_path);
if (!result && (i < retry_count)) {
Sleep(1);
} else {
EXPECT_TRUE(result) << "Failed to delete directory \"" << path << "\": " << GetLastError(); return;
}
}
}
staticwchar_t* my_wcscpy_s(wchar_t* dest, size_t size, wchar_t* start, constwchar_t* to_copy) {
size_t already_used = dest - start;
size_t len = wcslen(to_copy);
if (already_used + len < size) {
wcscpy_s(dest, size - already_used, to_copy);
}
return dest + wcslen(to_copy);
}
// The currently finite list of seperator sequences we might use instead of '\\'. staticconstwchar_t* sep_replacements[] = {
L"\\", L"\\/", L"/", L"//", L"\\\\/\\", L"//\\/"
};
// Takes a path and modifies it in a way that it should still designate the same file. staticbool unnormalize_path(wchar_t* result, size_t size, bool is_dir, constwchar_t* path) { wchar_t* dest = result; constwchar_t* src = path; constwchar_t* path_start;
if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) { struct stat st; int stat_ret;
EXPECT_EQ(stat_ret = os::stat(buf, &st), -1) << "os::stat did not fail for \"" << path << "\""; if (stat_ret != -1) { // Only check open if stat not already failed. int fd = os::open(buf, O_RDONLY, 0);
EXPECT_EQ(fd, -1) << "os::open did not fail for \"" << path << "\""; if (fd >= 0) {
::close(fd);
}
}
}
}
if (tmp) { if (_wfullpath(tmp, w_path, JVM_MAXPATHLEN)) {
succ = true;
}
// Note that we really don't use the full path name, but just add the cost of running _wfullpath.
os::free(tmp);
} if (!succ) {
printf("Failed fullpathing \"%s\"\n", buf); return;
}
succ = false;
}
HANDLE h = ::CreateFileW(w_path, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
for (int i = 0; i < reps; ++i) {
HANDLE h = ::CreateFileA(buf, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (h == INVALID_HANDLE_VALUE) { return;
}
::CloseHandle(h);
}
ctime = os::javaTimeNanos() - ctime;
printf("\"%s\" %f us for *A, %f us for *W, %f us for *W with fullpath\n", buf,
0.001 * ctime / reps, 0.001 * wtime[0] / reps, 0.001 * wtime[1] / reps);
}
}
// For UNC path test we assume that the current DRIVE has a share // called "<DRIVELETTER>$" (so for D: we expect \\localhost\D$ to be // the same). Since this is only an assumption, we have to skip // the UNC tests if the share is missing. if (dir_letter && !::GetFileAttributesExW(nearly_long_unc_path, GetFileExInfoStandard, &file_data)) {
printf("Disabled UNC path test, since %lc: is not mapped as share %lc$.\n", dir_letter, dir_letter);
} else {
can_test_unc = true;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.