/************************************************************************** * File name : MemoryArea.java * * This file is part a SCJ Level 0 and Level 1 implementation, * based on SCJ Draft, Version 0.94 25 June 2013. * * It is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This SCJ Level 0 and Level 1 implementation is distributed in the hope * that it will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this SCJ Level 0 and Level 1 implementation. * If not, see <http://www.gnu.org/licenses/>. * * Copyright 2012 * @authors Anders P. Ravn, Aalborg University, DK * Stephan E. Korsholm and Hans Søndergaard, * VIA University College, DK *************************************************************************/ package javax.realtime; import icecaptools.IcecapCompileMe; import javax.safetycritical.annotate.Level; import javax.safetycritical.annotate.SCJAllowed; import reflect.ObjectInfo; import vm.Memory; /** * All allocation contexts are implemented by memory areas. This is the * base-level class for all memory areas. * * @version 1.2; - December 2013 * * @author Anders P. Ravn, Aalborg University, <A * HREF="mailto:apr@cs.aau.dk">apr@cs.aau.dk</A>, <br> * Hans Søndergaard, VIA University College, Denmark, <A * HREF="mailto:hso@viauc.dk">hso@via.dk</A> */ @SCJAllowed(Level.INFRASTRUCTURE) public abstract class MemoryArea extends Object { /* The global over all backing store area. This is the root area of * all other areas. It does not have a provider. */ public static MemoryArea overAllBackingStore; // ------------------------------------------------------------------- // Backing store for this memory area: /* The MemoryArea providing the backing store for this MemoryArea */ protected MemoryArea backingStoreProvider; /* The head of a linked list of MemoryAreas contained in this MemoryArea (provided by this MemoryArea) */ private MemoryArea headOfContainedMemories; private MemoryArea nextContainedMemory; // ------------------------------------------------------------------- // Allocation area: protected Memory delegate; private int reservedEnd; private int maxUsage; /** * Dummy constructor for javax.realtime.ImmortalMemory */ protected MemoryArea() { } /** * Dummy constructor for javax.safetycritical.ManagedMemory.BackingStore */ protected MemoryArea(Memory delegate) { this.delegate = delegate; reservedEnd = delegate.getBase() + delegate.getSize(); delegate.resize(0); } /** * Creates a new memory area. * * @param initialSize * The initial size of this new memory area * * @param reservedSize * The size of the reserved area in the backing store in which this memory area is located. This must be * larger than or the same as the initialSize */ // /*@ // behavior // requires size > 0; // ensures size() == size && memoryConsumed() == 0; // @*/ @IcecapCompileMe protected MemoryArea(int initialSize, int reservedSize, MemoryArea backingStoreProvider, String label) { int base = backingStoreProvider.reservedEnd - backingStoreProvider.getRemainingBackingstoreSize(); int endOfAvailableSpace = backingStoreProvider.reservedEnd; if (base + reservedSize <= endOfAvailableSpace) { this.backingStoreProvider = backingStoreProvider; delegate = new Memory(base, initialSize, label); reservedEnd = base + reservedSize; backingStoreProvider.addContainedMemory(this); } else { System.out.println(" MemoryArea: throw " + label); throw new OutOfMemoryError("thrown from MemoryArea :: constructor : Out of backingstore exception: size: " + initialSize + " backingStoreSize: " + reservedSize + " base: " + base + " backingStoreEnd: " + endOfAvailableSpace); } } private void addContainedMemory(MemoryArea memoryArea) { memoryArea.nextContainedMemory = headOfContainedMemories; headOfContainedMemories = memoryArea; if (memoryArea.reservedEnd > maxUsage) { maxUsage = memoryArea.reservedEnd; } } private void removeContainedMemory(MemoryArea memoryArea) { if (headOfContainedMemories == memoryArea) { headOfContainedMemories = headOfContainedMemories.nextContainedMemory; } else { MemoryArea current = headOfContainedMemories; while (current.nextContainedMemory != null) { if (current.nextContainedMemory == memoryArea) { current.nextContainedMemory = current.nextContainedMemory.nextContainedMemory; return; } current = current.nextContainedMemory; } } } /** * Removes <code>this</code> area from the open list with head <code>head</code>. * The head is ImmortalMemory and is never removed. */ protected void removeMemArea() { if (this != overAllBackingStore) { backingStoreProvider.removeContainedMemory(this); } } /** * @return The memory consumed (in bytes) in this memory area. */ @SCJAllowed public long memoryConsumed() { return (long) delegate.consumedMemory(); } /** * @return The memory remaining (in bytes) in this memory area. */ @SCJAllowed public long memoryRemaining() { return size() - memoryConsumed(); } /** * @return The size of the current memory area in bytes. */ @SCJAllowed public long size() { return this.delegate.getSize(); } protected void resizeMemArea(long newSize) { if (memoryConsumed() < newSize) { if (this.delegate.getBase() + newSize < reservedEnd) { if (headOfContainedMemories == null) { delegate.resize((int) newSize); return; } } } throw new OutOfMemoryError("thrown from MemoryArea :: resizeMem : Out of backingstore exception "); } /** * get the overall remaining backing store size. * * @return the overall remaining backing store size. */ // Not public in SCJ public static int getRemainingMemorySize() { return overAllBackingStore.getRemainingBackingstoreSize(); } // Not public in SCJ public int getRemainingBackingstoreSize() { int maxEnd = delegate.getBase() + delegate.getSize(); MemoryArea current = headOfContainedMemories; while (current != null) { maxEnd = maxEnd > current.reservedEnd ? maxEnd : current.reservedEnd; current = current.nextContainedMemory; } return reservedEnd - maxEnd; } @Override public String toString() { return delegate.toString(); } // for test purpose public static void printMemoryAreas() { print(overAllBackingStore, 0); } protected static MemoryArea getNamedMemoryArea(String name) { return getNamedMemoryArea(overAllBackingStore, name); } private static MemoryArea getNamedMemoryArea(MemoryArea provider, String name) { if (provider.delegate.getName().equals(name)) { return provider; } MemoryArea current = provider.headOfContainedMemories; while (current != null) { MemoryArea result = getNamedMemoryArea(current, name); if (result != null) { return result; } current = current.nextContainedMemory; } return null; } /** * @param object An object. * @return The memory area in which <code>object</code> is allocated. */ @SCJAllowed public static MemoryArea getMemoryArea(Object object) { int ref = ObjectInfo.getAddress(object); return getMemoryArea(overAllBackingStore, ref); } private static MemoryArea getMemoryArea(MemoryArea provider, int ref) { if ((provider.delegate.getBase() <= ref) && (ref < provider.delegate.getBase() + provider.delegate.getSize())) { return provider; } MemoryArea current = provider.headOfContainedMemories; while (current != null) { MemoryArea result = getMemoryArea(current, ref); if (result != null) { //System.out.println("MemoryArea.result: " + result); return result; } current = current.nextContainedMemory; } return null; } protected static MemoryArea getCurrentMemoryArea() { vm.Memory mem = vm.Memory.getCurrentMemoryArea(); return getCurrentMemoryArea (overAllBackingStore, mem); } static MemoryArea getCurrentMemoryArea (MemoryArea provider, Memory mem) { if (provider.delegate == mem) { return provider; } MemoryArea current = provider.headOfContainedMemories; while (current != null) { MemoryArea result = getCurrentMemoryArea(current, mem); if (result != null) { return result; } current = current.nextContainedMemory; } return null; } private static void print(MemoryArea backingStoreProvider, int indent) { MemoryArea current = backingStoreProvider.headOfContainedMemories; int count = indent; while (count > 0) { devices.Console.print(" "); count--; } int bsstart = backingStoreProvider.delegate.getBase() + backingStoreProvider.delegate.getSize(); devices.Console.print(backingStoreProvider.delegate.getName() + "[used " + backingStoreProvider.delegate.consumedMemory() + " of " + backingStoreProvider.delegate.getSize()); int bssize = backingStoreProvider.reservedEnd - bsstart; if (bssize > 0) { int consumedBackingStore; if (backingStoreProvider.maxUsage > 0) { consumedBackingStore = backingStoreProvider.maxUsage - bsstart; } else { consumedBackingStore = 0; } devices.Console.println(", used " + consumedBackingStore + " of " + bssize + "]"); } else { devices.Console.println("]"); } while (current != null) { print(current, indent + 1); current = current.nextContainedMemory; } } }