1 /*
   2  * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2020 SAP SE. All rights reserved.
   4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5  *
   6  * This code is free software; you can redistribute it and/or modify it
   7  * under the terms of the GNU General Public License version 2 only, as
   8  * published by the Free Software Foundation.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  *
  24  */
  25 
  26 #include "precompiled.hpp"
  27 
  28 #include "memory/metaspace/commitMask.hpp"
  29 #include "memory/metaspace/metaspaceCommon.hpp"
  30 #include "memory/metaspace/settings.hpp"
  31 #include "runtime/stubRoutines.hpp"
  32 
  33 #include "utilities/align.hpp"
  34 #include "utilities/debug.hpp"
  35 
  36 namespace metaspace {
  37 
  38 CommitMask::CommitMask(const MetaWord* start, size_t word_size)
  39   : CHeapBitMap(mask_size(word_size, Settings::commit_granule_words()))
  40   , _base(start)
  41   , _word_size(word_size)
  42   , _words_per_bit(Settings::commit_granule_words())
  43 {
  44   assert(_word_size > 0 && _words_per_bit > 0 &&
  45          is_aligned(_word_size, _words_per_bit), "Sanity");
  46 }
  47 
  48 #ifdef ASSERT
  49 
  50 // This is very expensive
  51 static const bool TEST_UNCOMMITTED_REGION = false;
  52 
  53 volatile u1 x;
  54 
  55 static void check_range_is_accessible(const MetaWord* p, size_t word_size) {
  56   const MetaWord* const p_end = p + word_size;
  57   u1 x2 = 0;
  58   for (const MetaWord* q = p; q < p_end; q += os::vm_page_size() / BytesPerWord) {
  59     x2 += *(u1*)q;
  60   }
  61   x = x2;
  62 }
  63 
  64 void CommitMask::verify(bool slow) const {
  65 
  66   // Walk the whole commit mask.
  67   // For each 1 bit, check if the associated granule is accessible.
  68   // For each 0 bit, check if the associated granule is not accessible. Slow mode only.
  69 
  70   assert(_base != NULL && _word_size > 0 && _words_per_bit > 0, "Sanity");
  71   assert_is_aligned(_base, _words_per_bit * BytesPerWord);
  72   assert_is_aligned(_word_size, _words_per_bit);
  73 
  74   if (slow) {
  75     for (idx_t i = 0; i < size(); i ++) {
  76       const MetaWord* const p = _base + (i * _words_per_bit);
  77       if (at(i)) {
  78         // Should be accessible. Just touch it.
  79         check_range_is_accessible(p, _words_per_bit);
  80       } else {
  81         // Note: results may differ between platforms. On Linux, this should be true since
  82         // we uncommit memory by setting protection to PROT_NONE. We may have to look if
  83         // this works as expected on other platforms.
  84         if (TEST_UNCOMMITTED_REGION && CanUseSafeFetch32()) {
  85           assert(os::is_readable_pointer(p) == false,
  86                  "index %u, pointer " PTR_FORMAT ", should not be accessible.",
  87                  (unsigned)i, p2i(p));
  88         }
  89       }
  90     }
  91   }
  92 
  93 }
  94 
  95 #endif // ASSERT
  96 
  97 void CommitMask::print_on(outputStream* st) const {
  98 
  99   st->print("commit mask, base " PTR_FORMAT ":", p2i(base()));
 100 
 101   for (idx_t i = 0; i < size(); i ++) {
 102     st->print("%c", at(i) ? 'X' : '-');
 103   }
 104 
 105   st->cr();
 106 
 107 }
 108 
 109 } // namespace metaspace
 110