1 /*
   2  * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2018, 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 
  27 #include "precompiled.hpp"
  28 #include "metaspace/metaspaceTestsCommon.hpp"
  29 #include "metaspace/metaspaceTestContexts.hpp"
  30 
  31 using namespace metaspace::chunklevel;
  32 
  33 
  34 void ChunkTestsContext::checked_alloc_chunk_0(Metachunk** p_return_value, chunklevel_t preferred_level, chunklevel_t max_level,
  35                                                       size_t min_committed_size) {
  36 
  37   *p_return_value = NULL;
  38 
  39   Metachunk* c = cm().get_chunk(preferred_level, max_level, min_committed_size);
  40 
  41   if (c != NULL) {
  42 
  43     ASSERT_LE(c->level(), max_level);
  44     ASSERT_GE(c->level(), preferred_level);
  45     ASSERT_GE(c->committed_words(), min_committed_size);
  46     ASSERT_EQ(c->committed_words(), c->free_below_committed_words());
  47     ASSERT_EQ(c->used_words(), (size_t)0);
  48     ASSERT_TRUE(c->is_in_use());
  49     ASSERT_FALSE(c->is_free());
  50     ASSERT_FALSE(c->is_dead());
  51     ASSERT_NULL(c->next());
  52     ASSERT_NULL(c->prev());
  53     if (c->level() == HIGHEST_CHUNK_LEVEL) {
  54       ASSERT_TRUE(c->is_leaf_chunk());
  55     } else {
  56       ASSERT_FALSE(c->is_leaf_chunk());
  57     }
  58     if (c->level() == LOWEST_CHUNK_LEVEL) {
  59       ASSERT_TRUE(c->is_root_chunk());
  60     } else {
  61       ASSERT_FALSE(c->is_root_chunk());
  62     }
  63     if (_num_chunks_allocated == 0) { // First chunk? We can make more assumptions
  64       ASSERT_EQ(c->level(), preferred_level);
  65       // Needs lock EXPECT_NULL(c->next_in_vs());
  66       // Needs lock EXPECT_NULL(c->prev_in_vs());
  67       ASSERT_TRUE(c->is_root_chunk() || c->is_leader());
  68     }
  69     _num_chunks_allocated ++;
  70 
  71   }
  72 
  73   *p_return_value = c;
  74 
  75 }
  76 
  77 // Test pattern established when allocating from the chunk with allocate_from_chunk_with_tests().
  78 void ChunkTestsContext::test_pattern(Metachunk* c, size_t word_size) {
  79   check_range_for_pattern(c->base(), word_size, (uintx)c);
  80 }
  81 
  82 void ChunkTestsContext::return_chunk(Metachunk* c) {
  83   test_pattern(c);
  84   c->set_in_use(); // Forestall assert in cm
  85   cm().return_chunk(c);
  86 }
  87 
  88  void ChunkTestsContext::allocate_from_chunk(MetaWord** p_return_value, Metachunk* c, size_t word_size) {
  89 
  90   size_t used_before = c->used_words();
  91   size_t free_before = c->free_words();
  92   size_t free_below_committed_before = c->free_below_committed_words();
  93   const MetaWord* top_before = c->top();
  94 
  95   MetaWord* p = c->allocate(word_size);
  96   EXPECT_NOT_NULL(p);
  97   EXPECT_EQ(c->used_words(), used_before + word_size);
  98   EXPECT_EQ(c->free_words(), free_before - word_size);
  99   EXPECT_EQ(c->free_below_committed_words(), free_below_committed_before - word_size);
 100   EXPECT_EQ(c->top(), top_before + word_size);
 101 
 102   // Old content should be preserved
 103   test_pattern(c, used_before);
 104 
 105   // Fill newly allocated range too
 106   fill_range_with_pattern(p, word_size, (uintx)c);
 107 
 108   *p_return_value = p;
 109 }
 110 
 111 void ChunkTestsContext::commit_chunk_with_test(Metachunk* c, size_t additional_size) {
 112 
 113   size_t used_before = c->used_words();
 114   size_t free_before = c->free_words();
 115   const MetaWord* top_before = c->top();
 116 
 117   c->set_in_use();
 118   bool b = c->ensure_committed_additional(additional_size);
 119   EXPECT_TRUE(b);
 120 
 121   // We should have enough committed size now
 122   EXPECT_GE(c->free_below_committed_words(), additional_size);
 123 
 124   // used, free, top should be unchanged.
 125   EXPECT_EQ(c->used_words(), used_before);
 126   EXPECT_EQ(c->free_words(), free_before);
 127   EXPECT_EQ(c->top(), top_before);
 128 
 129   test_pattern(c, used_before);
 130 
 131 }
 132 
 133 void ChunkTestsContext::commit_chunk_expect_failure(Metachunk* c, size_t additional_size) {
 134 
 135   size_t used_before = c->used_words();
 136   size_t free_before = c->free_words();
 137   size_t free_below_committed_before = c->free_below_committed_words();
 138   const MetaWord* top_before = c->top();
 139 
 140   c->set_in_use();
 141   bool b = c->ensure_committed_additional(additional_size);
 142   EXPECT_FALSE(b);
 143 
 144   // Nothing should have changed
 145   EXPECT_EQ(c->used_words(), used_before);
 146   EXPECT_EQ(c->free_words(), free_before);
 147   EXPECT_EQ(c->free_below_committed_words(), free_below_committed_before);
 148   EXPECT_EQ(c->top(), top_before);
 149 
 150   test_pattern(c, used_before);
 151 
 152 }
 153 
 154 void ChunkTestsContext::uncommit_chunk_with_test(Metachunk* c) {
 155   if (c->word_size() >= Settings::commit_granule_words()) {
 156     c->set_free();  // Forestall assert in uncommit
 157     c->reset_used_words();
 158     c->uncommit();
 159 
 160     EXPECT_EQ(c->free_below_committed_words(), (size_t)0);
 161     EXPECT_EQ(c->used_words(), (size_t)0);
 162     EXPECT_EQ(c->free_words(), c->word_size());
 163     EXPECT_EQ(c->top(), c->base());
 164     EXPECT_TRUE(c->is_fully_uncommitted());
 165   }
 166 }
 167 
 168 
 169 
 170 /////// SparseArray<T> ////////////////
 171 
 172 
 173