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 #include "memory/metaspace/chunkLevel.hpp" 28 #include "memory/metaspace/freeChunkList.hpp" 29 #include "utilities/globalDefinitions.hpp" 30 #include "utilities/debug.hpp" 31 #include "utilities/ostream.hpp" 32 33 34 35 namespace metaspace { 36 37 void FreeChunkList::print_on(outputStream* st) const { 38 39 if (_num_chunks.get() > 0) { 40 for (const Metachunk* c = _first; c != NULL; c = c->next()) { 41 st->print(" - <"); 42 c->print_on(st); 43 st->print(">"); 44 } 45 st->print(" - total : %d chunks.", _num_chunks.get()); 46 } else { 47 st->print("empty"); 48 } 49 50 } 51 52 #ifdef ASSERT 53 54 bool FreeChunkList::contains(const Metachunk* c) const { 55 for (Metachunk* c2 = _first; c2 != NULL; c2 = c2->next()) { 56 if (c2 == c) { 57 return true; 58 } 59 } 60 return false; 61 } 62 63 void FreeChunkList::verify() const { 64 65 if (_first == NULL) { 66 assert(_last == NULL, "Sanity"); 67 } else { 68 assert(_last != NULL, "Sanity"); 69 size_t committed = 0; 70 int num = 0; 71 bool uncommitted = (_first->committed_words() == 0); 72 for (Metachunk* c = _first; c != NULL; c = c->next()) { 73 assert(c->is_free(), "Chunks in freelist should be free"); 74 assert(c->used_words() == 0, "Chunk in freelist should have not used words."); 75 assert(c->level() == _first->level(), "wrong level"); 76 assert(c->next() == NULL || c->next()->prev() == c, "front link broken"); 77 assert(c->prev() == NULL || c->prev()->next() == c, "back link broken"); 78 assert(c != c->prev() && c != c->next(), "circle"); 79 c->verify(false); 80 committed += c->committed_words(); 81 num ++; 82 } 83 _num_chunks.check(num); 84 _committed_word_size.check(committed); 85 } 86 87 } 88 89 #endif // ASSERT 90 91 92 // Returns total size in all lists (regardless of commit state of underlying memory) 93 size_t FreeChunkListVector::word_size() const { 94 size_t sum = 0; 95 for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l ++) { 96 sum += list_for_level(l)->num_chunks() * chunklevel::word_size_for_level(l); 97 } 98 return sum; 99 } 100 101 // Returns total committed size in all lists 102 size_t FreeChunkListVector::committed_word_size() const { 103 size_t sum = 0; 104 for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l ++) { 105 sum += list_for_level(l)->committed_word_size(); 106 } 107 return sum; 108 } 109 110 // Returns total committed size in all lists 111 int FreeChunkListVector::num_chunks() const { 112 int n = 0; 113 for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l ++) { 114 n += list_for_level(l)->num_chunks(); 115 } 116 return n; 117 } 118 119 120 // Look for a chunk: starting at level, up to and including max_level, 121 // return the first chunk whose committed words >= min_committed_words. 122 // Return NULL if no such chunk was found. 123 Metachunk* FreeChunkListVector::search_chunk_ascending(chunklevel_t level, chunklevel_t max_level, size_t min_committed_words) { 124 assert(min_committed_words <= chunklevel::word_size_for_level(max_level), 125 "min chunk size too small to hold min_committed_words"); 126 for (chunklevel_t l = level; l <= max_level; l ++) { 127 Metachunk* c = list_for_level(l)->first(); 128 if (c != NULL && c->committed_words() >= min_committed_words) { 129 list_for_level(l)->remove(c); 130 return c; 131 } 132 } 133 return NULL; 134 } 135 136 // Look for a chunk: starting at level, down to (including) the root chunk level, 137 // return the first chunk whose committed words >= min_committed_words. 138 // Return NULL if no such chunk was found. 139 Metachunk* FreeChunkListVector::search_chunk_descending(chunklevel_t level, size_t min_committed_words) { 140 for (chunklevel_t l = level; l >= chunklevel::LOWEST_CHUNK_LEVEL; l --) { 141 Metachunk* c = list_for_level(l)->first(); 142 if (c != NULL && c->committed_words() >= min_committed_words) { 143 list_for_level(l)->remove(c); 144 return c; 145 } 146 } 147 return NULL; 148 } 149 150 void FreeChunkListVector::print_on(outputStream* st) const { 151 for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l ++) { 152 st->print("-- List[" CHKLVL_FORMAT "]: ", l); 153 list_for_level(l)->print_on(st); 154 st->cr(); 155 } 156 st->print_cr("total chunks: %d, total word size: " SIZE_FORMAT ", committed word size: " SIZE_FORMAT ".", 157 num_chunks(), word_size(), committed_word_size()); 158 } 159 160 161 #ifdef ASSERT 162 163 void FreeChunkListVector::verify() const { 164 for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l ++) { 165 list_for_level(l)->verify(); 166 } 167 } 168 169 bool FreeChunkListVector::contains(const Metachunk* c) const { 170 for (chunklevel_t l = chunklevel::LOWEST_CHUNK_LEVEL; l <= chunklevel::HIGHEST_CHUNK_LEVEL; l ++) { 171 if (list_for_level(l)->contains(c)) { 172 return true; 173 } 174 } 175 return false; 176 } 177 178 #endif // ASSERT 179 180 181 182 } // namespace metaspace 183