5939 struct stat st;
5940 int ret = os::stat(filename, &st);
5941 assert(ret == 0, "failed to stat() file '%s': %s", filename, strerror(errno));
5942 return st.st_mtim;
5943 }
5944
5945 int os::compare_file_modified_times(const char* file1, const char* file2) {
5946 struct timespec filetime1 = get_mtime(file1);
5947 struct timespec filetime2 = get_mtime(file2);
5948 int diff = filetime1.tv_sec - filetime2.tv_sec;
5949 if (diff == 0) {
5950 return filetime1.tv_nsec - filetime2.tv_nsec;
5951 }
5952 return diff;
5953 }
5954
5955 /////////////// Unit tests ///////////////
5956
5957 #ifndef PRODUCT
5958
5959 #define test_log(...) \
5960 do { \
5961 if (VerboseInternalVMTests) { \
5962 tty->print_cr(__VA_ARGS__); \
5963 tty->flush(); \
5964 } \
5965 } while (false)
5966
5967 class TestReserveMemorySpecial : AllStatic {
5968 public:
5969 static void small_page_write(void* addr, size_t size) {
5970 size_t page_size = os::vm_page_size();
5971
5972 char* end = (char*)addr + size;
5973 for (char* p = (char*)addr; p < end; p += page_size) {
5974 *p = 1;
5975 }
5976 }
5977
5978 static void test_reserve_memory_special_huge_tlbfs_only(size_t size) {
5979 if (!UseHugeTLBFS) {
5980 return;
5981 }
5982
5983 test_log("test_reserve_memory_special_huge_tlbfs_only(" SIZE_FORMAT ")", size);
5984
5985 char* addr = os::Linux::reserve_memory_special_huge_tlbfs_only(size, NULL, false);
5986
5987 if (addr != NULL) {
5988 small_page_write(addr, size);
5989
5990 os::Linux::release_memory_special_huge_tlbfs(addr, size);
5991 }
5992 }
5993
5994 static void test_reserve_memory_special_huge_tlbfs_only() {
5995 if (!UseHugeTLBFS) {
5996 return;
5997 }
5998
5999 size_t lp = os::large_page_size();
6000
6001 for (size_t size = lp; size <= lp * 10; size += lp) {
6002 test_reserve_memory_special_huge_tlbfs_only(size);
6003 }
6004 }
6023
6024 // Pre-allocate two areas; they shall be as large as the largest allocation
6025 // and aligned to the largest alignment we will be testing.
6026 const size_t mapping_size = sizes[num_sizes - 1] * 2;
6027 char* const mapping1 = (char*) ::mmap(NULL, mapping_size,
6028 PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE,
6029 -1, 0);
6030 assert(mapping1 != MAP_FAILED, "should work");
6031
6032 char* const mapping2 = (char*) ::mmap(NULL, mapping_size,
6033 PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE,
6034 -1, 0);
6035 assert(mapping2 != MAP_FAILED, "should work");
6036
6037 // Unmap the first mapping, but leave the second mapping intact: the first
6038 // mapping will serve as a value for a "good" req_addr (case 2). The second
6039 // mapping, still intact, as "bad" req_addr (case 3).
6040 ::munmap(mapping1, mapping_size);
6041
6042 // Case 1
6043 test_log("%s, req_addr NULL:", __FUNCTION__);
6044 test_log("size align result");
6045
6046 for (int i = 0; i < num_sizes; i++) {
6047 const size_t size = sizes[i];
6048 for (size_t alignment = ag; is_aligned(size, alignment); alignment *= 2) {
6049 char* p = os::Linux::reserve_memory_special_huge_tlbfs_mixed(size, alignment, NULL, false);
6050 test_log(SIZE_FORMAT_HEX " " SIZE_FORMAT_HEX " -> " PTR_FORMAT " %s",
6051 size, alignment, p2i(p), (p != NULL ? "" : "(failed)"));
6052 if (p != NULL) {
6053 assert(is_aligned(p, alignment), "must be");
6054 small_page_write(p, size);
6055 os::Linux::release_memory_special_huge_tlbfs(p, size);
6056 }
6057 }
6058 }
6059
6060 // Case 2
6061 test_log("%s, req_addr non-NULL:", __FUNCTION__);
6062 test_log("size align req_addr result");
6063
6064 for (int i = 0; i < num_sizes; i++) {
6065 const size_t size = sizes[i];
6066 for (size_t alignment = ag; is_aligned(size, alignment); alignment *= 2) {
6067 char* const req_addr = align_up(mapping1, alignment);
6068 char* p = os::Linux::reserve_memory_special_huge_tlbfs_mixed(size, alignment, req_addr, false);
6069 test_log(SIZE_FORMAT_HEX " " SIZE_FORMAT_HEX " " PTR_FORMAT " -> " PTR_FORMAT " %s",
6070 size, alignment, p2i(req_addr), p2i(p),
6071 ((p != NULL ? (p == req_addr ? "(exact match)" : "") : "(failed)")));
6072 if (p != NULL) {
6073 assert(p == req_addr, "must be");
6074 small_page_write(p, size);
6075 os::Linux::release_memory_special_huge_tlbfs(p, size);
6076 }
6077 }
6078 }
6079
6080 // Case 3
6081 test_log("%s, req_addr non-NULL with preexisting mapping:", __FUNCTION__);
6082 test_log("size align req_addr result");
6083
6084 for (int i = 0; i < num_sizes; i++) {
6085 const size_t size = sizes[i];
6086 for (size_t alignment = ag; is_aligned(size, alignment); alignment *= 2) {
6087 char* const req_addr = align_up(mapping2, alignment);
6088 char* p = os::Linux::reserve_memory_special_huge_tlbfs_mixed(size, alignment, req_addr, false);
6089 test_log(SIZE_FORMAT_HEX " " SIZE_FORMAT_HEX " " PTR_FORMAT " -> " PTR_FORMAT " %s",
6090 size, alignment, p2i(req_addr), p2i(p), ((p != NULL ? "" : "(failed)")));
6091 // as the area around req_addr contains already existing mappings, the API should always
6092 // return NULL (as per contract, it cannot return another address)
6093 assert(p == NULL, "must be");
6094 }
6095 }
6096
6097 ::munmap(mapping2, mapping_size);
6098
6099 }
6100
6101 static void test_reserve_memory_special_huge_tlbfs() {
6102 if (!UseHugeTLBFS) {
6103 return;
6104 }
6105
6106 test_reserve_memory_special_huge_tlbfs_only();
6107 test_reserve_memory_special_huge_tlbfs_mixed();
6108 }
6109
6110 static void test_reserve_memory_special_shm(size_t size, size_t alignment) {
6111 if (!UseSHM) {
6112 return;
6113 }
6114
6115 test_log("test_reserve_memory_special_shm(" SIZE_FORMAT ", " SIZE_FORMAT ")", size, alignment);
6116
6117 char* addr = os::Linux::reserve_memory_special_shm(size, alignment, NULL, false);
6118
6119 if (addr != NULL) {
6120 assert(is_aligned(addr, alignment), "Check");
6121 assert(is_aligned(addr, os::large_page_size()), "Check");
6122
6123 small_page_write(addr, size);
6124
6125 os::Linux::release_memory_special_shm(addr, size);
6126 }
6127 }
6128
6129 static void test_reserve_memory_special_shm() {
6130 size_t lp = os::large_page_size();
6131 size_t ag = os::vm_allocation_granularity();
6132
6133 for (size_t size = ag; size < lp * 3; size += ag) {
6134 for (size_t alignment = ag; is_aligned(size, alignment); alignment *= 2) {
6135 test_reserve_memory_special_shm(size, alignment);
6136 }
|
5939 struct stat st;
5940 int ret = os::stat(filename, &st);
5941 assert(ret == 0, "failed to stat() file '%s': %s", filename, strerror(errno));
5942 return st.st_mtim;
5943 }
5944
5945 int os::compare_file_modified_times(const char* file1, const char* file2) {
5946 struct timespec filetime1 = get_mtime(file1);
5947 struct timespec filetime2 = get_mtime(file2);
5948 int diff = filetime1.tv_sec - filetime2.tv_sec;
5949 if (diff == 0) {
5950 return filetime1.tv_nsec - filetime2.tv_nsec;
5951 }
5952 return diff;
5953 }
5954
5955 /////////////// Unit tests ///////////////
5956
5957 #ifndef PRODUCT
5958
5959 class TestReserveMemorySpecial : AllStatic {
5960 public:
5961 static void small_page_write(void* addr, size_t size) {
5962 size_t page_size = os::vm_page_size();
5963
5964 char* end = (char*)addr + size;
5965 for (char* p = (char*)addr; p < end; p += page_size) {
5966 *p = 1;
5967 }
5968 }
5969
5970 static void test_reserve_memory_special_huge_tlbfs_only(size_t size) {
5971 if (!UseHugeTLBFS) {
5972 return;
5973 }
5974
5975 char* addr = os::Linux::reserve_memory_special_huge_tlbfs_only(size, NULL, false);
5976
5977 if (addr != NULL) {
5978 small_page_write(addr, size);
5979
5980 os::Linux::release_memory_special_huge_tlbfs(addr, size);
5981 }
5982 }
5983
5984 static void test_reserve_memory_special_huge_tlbfs_only() {
5985 if (!UseHugeTLBFS) {
5986 return;
5987 }
5988
5989 size_t lp = os::large_page_size();
5990
5991 for (size_t size = lp; size <= lp * 10; size += lp) {
5992 test_reserve_memory_special_huge_tlbfs_only(size);
5993 }
5994 }
6013
6014 // Pre-allocate two areas; they shall be as large as the largest allocation
6015 // and aligned to the largest alignment we will be testing.
6016 const size_t mapping_size = sizes[num_sizes - 1] * 2;
6017 char* const mapping1 = (char*) ::mmap(NULL, mapping_size,
6018 PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE,
6019 -1, 0);
6020 assert(mapping1 != MAP_FAILED, "should work");
6021
6022 char* const mapping2 = (char*) ::mmap(NULL, mapping_size,
6023 PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE,
6024 -1, 0);
6025 assert(mapping2 != MAP_FAILED, "should work");
6026
6027 // Unmap the first mapping, but leave the second mapping intact: the first
6028 // mapping will serve as a value for a "good" req_addr (case 2). The second
6029 // mapping, still intact, as "bad" req_addr (case 3).
6030 ::munmap(mapping1, mapping_size);
6031
6032 // Case 1
6033 for (int i = 0; i < num_sizes; i++) {
6034 const size_t size = sizes[i];
6035 for (size_t alignment = ag; is_aligned(size, alignment); alignment *= 2) {
6036 char* p = os::Linux::reserve_memory_special_huge_tlbfs_mixed(size, alignment, NULL, false);
6037 if (p != NULL) {
6038 assert(is_aligned(p, alignment), "must be");
6039 small_page_write(p, size);
6040 os::Linux::release_memory_special_huge_tlbfs(p, size);
6041 }
6042 }
6043 }
6044
6045 // Case 2
6046 for (int i = 0; i < num_sizes; i++) {
6047 const size_t size = sizes[i];
6048 for (size_t alignment = ag; is_aligned(size, alignment); alignment *= 2) {
6049 char* const req_addr = align_up(mapping1, alignment);
6050 char* p = os::Linux::reserve_memory_special_huge_tlbfs_mixed(size, alignment, req_addr, false);
6051 if (p != NULL) {
6052 assert(p == req_addr, "must be");
6053 small_page_write(p, size);
6054 os::Linux::release_memory_special_huge_tlbfs(p, size);
6055 }
6056 }
6057 }
6058
6059 // Case 3
6060 for (int i = 0; i < num_sizes; i++) {
6061 const size_t size = sizes[i];
6062 for (size_t alignment = ag; is_aligned(size, alignment); alignment *= 2) {
6063 char* const req_addr = align_up(mapping2, alignment);
6064 char* p = os::Linux::reserve_memory_special_huge_tlbfs_mixed(size, alignment, req_addr, false);
6065 // as the area around req_addr contains already existing mappings, the API should always
6066 // return NULL (as per contract, it cannot return another address)
6067 assert(p == NULL, "must be");
6068 }
6069 }
6070
6071 ::munmap(mapping2, mapping_size);
6072
6073 }
6074
6075 static void test_reserve_memory_special_huge_tlbfs() {
6076 if (!UseHugeTLBFS) {
6077 return;
6078 }
6079
6080 test_reserve_memory_special_huge_tlbfs_only();
6081 test_reserve_memory_special_huge_tlbfs_mixed();
6082 }
6083
6084 static void test_reserve_memory_special_shm(size_t size, size_t alignment) {
6085 if (!UseSHM) {
6086 return;
6087 }
6088
6089 char* addr = os::Linux::reserve_memory_special_shm(size, alignment, NULL, false);
6090
6091 if (addr != NULL) {
6092 assert(is_aligned(addr, alignment), "Check");
6093 assert(is_aligned(addr, os::large_page_size()), "Check");
6094
6095 small_page_write(addr, size);
6096
6097 os::Linux::release_memory_special_shm(addr, size);
6098 }
6099 }
6100
6101 static void test_reserve_memory_special_shm() {
6102 size_t lp = os::large_page_size();
6103 size_t ag = os::vm_allocation_granularity();
6104
6105 for (size_t size = ag; size < lp * 3; size += ag) {
6106 for (size_t alignment = ag; is_aligned(size, alignment); alignment *= 2) {
6107 test_reserve_memory_special_shm(size, alignment);
6108 }
|