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 
  28 static size_t small_page_size() {
  29   return os::vm_page_size();
  30 }
  31 
  32 static size_t large_page_size() {
  33   const size_t large_page_size_example = 4 * M;
  34   return os::page_size_for_region_aligned(large_page_size_example, 1);
  35 }
  36 
  37 TEST_VM(os, page_size_for_region) {
  38   size_t large_page_example = 4 * M;
  39   size_t large_page = os::page_size_for_region_aligned(large_page_example, 1);
  40 
  41   size_t small_page = os::vm_page_size();
  42   if (large_page > small_page) {
  43     size_t num_small_in_large = large_page / small_page;
  44     size_t page = os::page_size_for_region_aligned(large_page, num_small_in_large);
  45     ASSERT_EQ(page, small_page) << "Did not get a small page";
  46   }
  47 }
  48 
  49 TEST_VM(os, page_size_for_region_aligned) {
  50   if (UseLargePages) {
  51     const size_t small_page = small_page_size();
  52     const size_t large_page = large_page_size();
  53 
  54     if (large_page > small_page) {
  55       size_t num_small_pages_in_large = large_page / small_page;
  56       size_t page = os::page_size_for_region_aligned(large_page, num_small_pages_in_large);
  57 
  58       ASSERT_EQ(page, small_page);
  59     }
  60   }
  61 }
  62 
  63 TEST_VM(os, page_size_for_region_alignment) {
  64   if (UseLargePages) {
  65     const size_t small_page = small_page_size();
  66     const size_t large_page = large_page_size();
  67     if (large_page > small_page) {
  68       const size_t unaligned_region = large_page + 17;
  69       size_t page = os::page_size_for_region_aligned(unaligned_region, 1);
  70       ASSERT_EQ(page, small_page);
  71 
  72       const size_t num_pages = 5;
  73       const size_t aligned_region = large_page * num_pages;
  74       page = os::page_size_for_region_aligned(aligned_region, num_pages);
  75       ASSERT_EQ(page, large_page);
  76     }
  77   }
  78 }
  79 
  80 TEST_VM(os, page_size_for_region_unaligned) {
  81   if (UseLargePages) {
  82     // Given exact page size, should return that page size.
  83     for (size_t i = 0; os::_page_sizes[i] != 0; i++) {
  84       size_t expected = os::_page_sizes[i];
  85       size_t actual = os::page_size_for_region_unaligned(expected, 1);
  86       ASSERT_EQ(expected, actual);
  87     }
  88 
  89     // Given slightly larger size than a page size, return the page size.
  90     for (size_t i = 0; os::_page_sizes[i] != 0; i++) {
  91       size_t expected = os::_page_sizes[i];
  92       size_t actual = os::page_size_for_region_unaligned(expected + 17, 1);
  93       ASSERT_EQ(expected, actual);
  94     }
  95 
  96     // Given a slightly smaller size than a page size,
  97     // return the next smaller page size.
  98     if (os::_page_sizes[1] > os::_page_sizes[0]) {
  99       size_t expected = os::_page_sizes[0];
 100       size_t actual = os::page_size_for_region_unaligned(os::_page_sizes[1] - 17, 1);
 101       ASSERT_EQ(actual, expected);
 102     }
 103 
 104     // Return small page size for values less than a small page.
 105     size_t small_page = small_page_size();
 106     size_t actual = os::page_size_for_region_unaligned(small_page - 17, 1);
 107     ASSERT_EQ(small_page, actual);
 108   }
 109 }
 110 
 111 TEST(os, test_random) {
 112   const double m = 2147483647;
 113   double mean = 0.0, variance = 0.0, t;
 114   const int reps = 10000;
 115   unsigned int seed = 1;
 116 
 117   // tty->print_cr("seed %ld for %ld repeats...", seed, reps);
 118   os::init_random(seed);
 119   int num;
 120   for (int k = 0; k < reps; k++) {
 121     num = os::random();
 122     double u = (double)num / m;
 123     ASSERT_TRUE(u >= 0.0 && u <= 1.0) << "bad random number!";
 124 
 125     // calculate mean and variance of the random sequence
 126     mean += u;
 127     variance += (u*u);
 128   }
 129   mean /= reps;
 130   variance /= (reps - 1);
 131 
 132   ASSERT_EQ(num, 1043618065) << "bad seed";
 133   // tty->print_cr("mean of the 1st 10000 numbers: %f", mean);
 134   int intmean = mean*100;
 135   ASSERT_EQ(intmean, 50);
 136   // tty->print_cr("variance of the 1st 10000 numbers: %f", variance);
 137   int intvariance = variance*100;
 138   ASSERT_EQ(intvariance, 33);
 139   const double eps = 0.0001;
 140   t = fabsd(mean - 0.5018);
 141   ASSERT_LT(t, eps) << "bad mean";
 142   t = (variance - 0.3355) < 0.0 ? -(variance - 0.3355) : variance - 0.3355;
 143   ASSERT_LT(t, eps) << "bad variance";
 144 }
 145 
 146 
 147 #ifdef ASSERT
 148 TEST_VM_ASSERT_MSG(os, page_size_for_region_with_zero_min_pages, "sanity") {
 149   size_t region_size = 16 * os::vm_page_size();
 150   os::page_size_for_region_aligned(region_size, 0); // should assert
 151 }
 152 #endif