/*
* $Id$
*
* Copyright (C) 2003-2014 JNode.org
*
* This library 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 2.1 of the License, or
* (at your option) any later version.
*
* This library 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 library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.vm;
import java.nio.ByteBuffer;
import java.nio.MemoryRawData;
import org.jnode.system.resource.MemoryResource;
import org.jnode.system.resource.MultiMediaMemoryResource;
import org.jnode.system.resource.Resource;
import org.jnode.system.resource.ResourceManager;
import org.jnode.system.resource.ResourceNotFreeException;
import org.jnode.system.resource.ResourceOwner;
import org.jnode.system.resource.SimpleResourceOwner;
import org.jnode.annotation.MagicPermission;
import org.jnode.vm.facade.VmUtils;
import org.jnode.vm.scheduler.VmProcessor;
import org.vmmagic.unboxed.Address;
import org.vmmagic.unboxed.Extent;
import org.vmmagic.unboxed.ObjectReference;
import org.vmmagic.unboxed.Offset;
import org.vmmagic.unboxed.Word;
/**
* Default implementation of MemoryResource.
*
* @author Ewout Prangsma (epr@users.sourceforge.net)
*/
@MagicPermission
class MemoryResourceImpl extends Region implements MemoryResource {
/**
* My parent
*/
private final MemoryResourceImpl parent;
/**
* Start address
*/
protected final Address start;
/**
* Exclusive end address
*/
private final Address end;
/**
* Size in bytes
*/
private final Extent size;
/**
* Has this resource been released?
*/
private boolean released;
/**
* First active memory-resource
*/
private static Region resources;
/**
* Data for mapping over byte arrays
*/
private final Object data;
/**
* Resource owner for byte arrays
*/
private static final ResourceOwner BYTE_ARRAY_OWNER = new SimpleResourceOwner("byte-array");
/**
* Size of an object reference
*/
private final int slotSize;
/**
* My children
*/
private MemoryResourceImpl children;
/**
* Offset relative to my parent
*/
private final Offset offset;
/**
* Create a new instance
*
* @param owner
* @param start
* @param size
*/
protected MemoryResourceImpl(MemoryResourceImpl parent, ResourceOwner owner, Address start, Extent size) {
super(owner);
this.parent = parent;
this.start = start;
if (parent != null) {
this.offset = start.toWord().sub(parent.start.toWord()).toOffset();
} else {
this.offset = start.toWord().toOffset();
}
this.end = start.add(size);
this.size = size;
this.released = false;
this.data = null;
this.slotSize = VmProcessor.current().getArchitecture().getReferenceSize();
}
/**
* Create a new instance
*
* @param arrayData
* @param length
* @param elementSize
*/
public MemoryResourceImpl(Object arrayData, int length, int elementSize) {
super(BYTE_ARRAY_OWNER);
this.parent = null;
this.data = arrayData;
this.size = Extent.fromIntZeroExtend(length * elementSize);
this.start = VmMagic.getArrayData(arrayData);
this.offset = start.toWord().toOffset();
this.end = start.add(length * elementSize);
this.released = false;
this.slotSize = VmProcessor.current().getArchitecture().getReferenceSize();
}
/**
* Create a bytebuffer that has the same content as this resource.
*
* @return a bytebuffer that has the same content as this resource
*/
public ByteBuffer asByteBuffer() {
return MemoryRawData.wrap(this);
}
/**
* Claim a memory region
*
* @param owner
* @param start
* @param size
* @param mode
* @return The claimed resource
* @throws ResourceNotFreeException
*/
protected static synchronized MemoryResource claimMemoryResource(ResourceOwner owner, Address start, Extent size,
int mode) throws ResourceNotFreeException {
if (start != null) {
final MemoryResourceImpl res = new MemoryResourceImpl(null, owner, start, size);
if (isFree(resources, res)) {
resources = add(resources, res);
return res;
} else {
throw new ResourceNotFreeException();
}
} else {
// Find a range
Address ptr;
if (mode == ResourceManager.MEMMODE_ALLOC_DMA) {
ptr = Unsafe.getMinAddress();
} else {
ptr = Unsafe.getMemoryEnd();
}
MemoryResourceImpl res = new MemoryResourceImpl(null, owner, ptr, size);
while (!isFree(resources, res)) {
ptr = ptr.add(64 * 1024);
res = new MemoryResourceImpl(null, owner, ptr, size);
}
resources = add(resources, res);
return res;
}
}
/**
* Gets a 8-bit signed byte at the given memory address
*
* @param memPtr
* @return byte
*/
public byte getByte(int memPtr) {
testMemPtr(memPtr, 1);
return start.loadByte(Offset.fromIntZeroExtend(memPtr));
}
/**
* Gets multiple 8-bit signed bytes from the given memory address
*
* @param memPtr
* @param dst
* @param dstOfs
* @param length
*/
public void getBytes(int memPtr, byte[] dst, int dstOfs, int length) {
if (dstOfs < 0) {
throw new IndexOutOfBoundsException("dstOfs < 0");
}
if (length < 0) {
throw new IndexOutOfBoundsException("length < 0");
}
if (dstOfs + length > dst.length) {
throw new IndexOutOfBoundsException("dstOfs + length > dst.length");
}
testMemPtr(memPtr, length);
final Address dstPtr = VmMagic.getArrayData(dst).add(dstOfs);
final Extent size = Extent.fromIntZeroExtend(length);
Unsafe.copy(start.add(Offset.fromIntZeroExtend(memPtr)), dstPtr, size);
}
/**
* Gets a 16-bit signed short at the given memory address
*
* @param memPtr
* @return short
*/
public short getShort(int memPtr) {
testMemPtr(memPtr, 2);
return start.loadShort(Offset.fromIntZeroExtend(memPtr));
}
/**
* Gets multiple 16-bit signed bytes from the given memory address
*
* @param memPtr
* @param dst
* @param dstOfs
* @param length
*/
public void getShorts(int memPtr, short[] dst, int dstOfs, int length) {
if (dstOfs < 0) {
throw new IndexOutOfBoundsException("dstOfs < 0");
}
if (length < 0) {
throw new IndexOutOfBoundsException("length < 0");
}
if (dstOfs + length > dst.length) {
throw new IndexOutOfBoundsException("dstOfs + length > dst.length");
}
testMemPtr(memPtr, length * 2);
final Address dstPtr = VmMagic.getArrayData(dst).add(dstOfs * 2);
final Extent size = Extent.fromIntZeroExtend(length * 2);
Unsafe.copy(start.add(Offset.fromIntZeroExtend(memPtr)), dstPtr, size);
}
/**
* Gets a 16-bit unsigned char at the given memory address
*
* @param memPtr
* @return char
*/
public char getChar(int memPtr) {
testMemPtr(memPtr, 2);
return start.loadChar(Offset.fromIntZeroExtend(memPtr));
}
/**
* Gets multiple 16-bit unsigned chars from the given memory address
*
* @param memPtr
* @param dst
* @param dstOfs
* @param length
*/
public void getChars(int memPtr, char[] dst, int dstOfs, int length) {
if (dstOfs < 0) {
throw new IndexOutOfBoundsException("dstOfs < 0");
}
if (length < 0) {
throw new IndexOutOfBoundsException("length < 0");
}
if (dstOfs + length > dst.length) {
throw new IndexOutOfBoundsException("dstOfs + length > dst.length");
}
testMemPtr(memPtr, length * 2);
final Address dstPtr = VmMagic.getArrayData(dst).add(dstOfs * 2);
final Extent size = Extent.fromIntZeroExtend(length * 2);
Unsafe.copy(start.add(Offset.fromIntZeroExtend(memPtr)), dstPtr, size);
}
/**
* Gets a 32-bit signed int at the given memory address
*
* @param memPtr
* @return int
*/
public int getInt(int memPtr) {
testMemPtr(memPtr, 4);
return start.loadInt(Offset.fromIntZeroExtend(memPtr));
}
/**
* Gets multiple 32-bit signed ints from the given memory address
*
* @param memPtr
* @param dst
* @param dstOfs
* @param length
*/
public void getInts(int memPtr, int[] dst, int dstOfs, int length) {
if (dstOfs < 0) {
throw new IndexOutOfBoundsException("dstOfs < 0");
}
if (length < 0) {
throw new IndexOutOfBoundsException("length < 0");
}
if (dstOfs + length > dst.length) {
throw new IndexOutOfBoundsException("dstOfs + length > dst.length");
}
testMemPtr(memPtr, length * 4);
final Address dstPtr = VmMagic.getArrayData(dst).add(dstOfs * 4);
final Extent size = Extent.fromIntZeroExtend(length * 4);
Unsafe.copy(start.add(Offset.fromIntZeroExtend(memPtr)), dstPtr, size);
}
/**
* Gets a 64-bit signed long at the given memory address
*
* @param memPtr
* @return long
*/
public long getLong(int memPtr) {
testMemPtr(memPtr, 8);
return start.loadLong(Offset.fromIntZeroExtend(memPtr));
}
/**
* Gets multiple 64-bit signed longs from the given memory address
*
* @param memPtr
* @param dst
* @param dstOfs
* @param length
*/
public void getLongs(int memPtr, long[] dst, int dstOfs, int length) {
if (dstOfs < 0) {
throw new IndexOutOfBoundsException("dstOfs < 0");
}
if (length < 0) {
throw new IndexOutOfBoundsException("length < 0");
}
if (dstOfs + length > dst.length) {
throw new IndexOutOfBoundsException("dstOfs + length > dst.length");
}
testMemPtr(memPtr, length * 8);
final Address dstPtr = VmMagic.getArrayData(dst).add(dstOfs * 8);
final Extent size = Extent.fromIntZeroExtend(length * 8);
Unsafe.copy(start.add(Offset.fromIntZeroExtend(memPtr)), dstPtr, size);
}
/**
* Gets a float at the given memory address
*
* @param memPtr
* @return float
*/
public float getFloat(int memPtr) {
testMemPtr(memPtr, 4);
return start.loadFloat(Offset.fromIntZeroExtend(memPtr));
}
/**
* Gets multiple 32-bit floats from the given memory address
*
* @param memPtr
* @param dst
* @param dstOfs
* @param length
*/
public void getFloats(int memPtr, float[] dst, int dstOfs, int length) {
if (dstOfs < 0) {
throw new IndexOutOfBoundsException("dstOfs < 0");
}
if (length < 0) {
throw new IndexOutOfBoundsException("length < 0");
}
if (dstOfs + length > dst.length) {
throw new IndexOutOfBoundsException("dstOfs + length > dst.length");
}
testMemPtr(memPtr, length * 4);
final Address dstPtr = VmMagic.getArrayData(dst).add(dstOfs * 4);
final Extent size = Extent.fromIntZeroExtend(length * 4);
Unsafe.copy(start.add(Offset.fromIntZeroExtend(memPtr)), dstPtr, size);
}
/**
* Gets a double at the given memory address
*
* @param memPtr
* @return double
*/
public double getDouble(int memPtr) {
testMemPtr(memPtr, 8);
return start.loadDouble(Offset.fromIntZeroExtend(memPtr));
}
/**
* Gets multiple 64-bit doubles from the given memory address
*
* @param memPtr
* @param dst
* @param dstOfs
* @param length
*/
public void getDoubles(int memPtr, double[] dst, int dstOfs, int length) {
if (dstOfs < 0) {
throw new IndexOutOfBoundsException("dstOfs < 0");
}
if (length < 0) {
throw new IndexOutOfBoundsException("length < 0");
}
if (dstOfs + length > dst.length) {
throw new IndexOutOfBoundsException("dstOfs + length > dst.length");
}
testMemPtr(memPtr, length * 8);
final Address dstPtr = VmMagic.getArrayData(dst).add(dstOfs * 8);
final Extent size = Extent.fromIntZeroExtend(length * 8);
Unsafe.copy(start.add(Offset.fromIntZeroExtend(memPtr)), dstPtr, size);
}
/**
* Gets a object reference at the given memory address
*
* @param memPtr
* @return Object
*/
public Object getObject(int memPtr) {
if (this.data != null) {
throw new SecurityException("Cannot get an Object from a byte-array");
}
testMemPtr(memPtr, 4);
return start.loadObjectReference(Offset.fromIntSignExtend(memPtr));
}
/**
* Sets a byte at a given memory address
*
* @param memPtr
* @param value
*/
public void setByte(int memPtr, byte value) {
testMemPtr(memPtr, 1);
start.store(value, Offset.fromIntSignExtend(memPtr));
}
/**
* Sets multiple 8-bit signed bytes at the given memory address
*
* @param src
* @param srcOfs
* @param dstPtr
* @param length
*/
public void setBytes(byte[] src, int srcOfs, int dstPtr, int length) {
if (srcOfs < 0) {
throw new IndexOutOfBoundsException("srcOfs < 0");
}
if (length < 0) {
throw new IndexOutOfBoundsException("length < 0");
}
if (srcOfs + length > src.length) {
throw new IndexOutOfBoundsException("srcOfs + length > src.length");
}
testMemPtr(dstPtr, length);
final Address srcPtr = VmMagic.getArrayData(src).add(srcOfs);
final Extent size = Extent.fromIntZeroExtend(length);
Unsafe.copy(srcPtr, start.add(dstPtr), size);
}
/**
* Sets a char at a given memory address
*
* @param memPtr
* @param value
*/
public void setChar(int memPtr, char value) {
testMemPtr(memPtr, 2);
start.store(value, Offset.fromIntSignExtend(memPtr));
}
/**
* Sets multiple 16-bit unsigned chars at the given memory address
*
* @param src
* @param srcOfs
* @param dstPtr
* @param length
*/
public void setChars(char[] src, int srcOfs, int dstPtr, int length) {
if (srcOfs < 0) {
throw new IndexOutOfBoundsException("srcOfs < 0");
}
if (length < 0) {
throw new IndexOutOfBoundsException("length < 0");
}
if (srcOfs + length > src.length) {
throw new IndexOutOfBoundsException("srcOfs + length > src.length");
}
testMemPtr(dstPtr, length * 2);
final Address srcPtr = VmMagic.getArrayData(src).add(srcOfs * 2);
final Extent size = Extent.fromIntZeroExtend(length * 2);
Unsafe.copy(srcPtr, start.add(dstPtr), size);
}
/**
* Sets a short at a given memory address
*
* @param memPtr
* @param value
*/
public void setShort(int memPtr, short value) {
testMemPtr(memPtr, 2);
start.store(value, Offset.fromIntSignExtend(memPtr));
}
/**
* Sets multiple 16-bit signed shorts at the given memory address
*
* @param src
* @param srcOfs
* @param dstPtr
* @param length
*/
public void setShorts(short[] src, int srcOfs, int dstPtr, int length) {
if (srcOfs < 0) {
throw new IndexOutOfBoundsException("srcOfs < 0");
}
if (length < 0) {
throw new IndexOutOfBoundsException("length < 0");
}
if (srcOfs + length > src.length) {
throw new IndexOutOfBoundsException("srcOfs + length > src.length");
}
testMemPtr(dstPtr, length * 2);
final Address srcPtr = VmMagic.getArrayData(src).add(srcOfs * 2);
final Extent size = Extent.fromIntZeroExtend(length * 2);
Unsafe.copy(srcPtr, start.add(dstPtr), size);
}
/**
* Sets an int at a given memory address
*
* @param memPtr
* @param value
*/
public void setInt(int memPtr, int value) {
testMemPtr(memPtr, 4);
start.store(value, Offset.fromIntSignExtend(memPtr));
}
/**
* Sets multiple 32-bit signed ints at the given memory address
*
* @param src
* @param srcOfs
* @param dstPtr
* @param length
*/
public void setInts(int[] src, int srcOfs, int dstPtr, int length) {
if (srcOfs < 0) {
throw new IndexOutOfBoundsException("srcOfs < 0");
}
if (length < 0) {
throw new IndexOutOfBoundsException("length < 0");
}
if (srcOfs + length > src.length) {
throw new IndexOutOfBoundsException("srcOfs + length > src.length");
}
testMemPtr(dstPtr, length * 4);
final Address srcPtr = VmMagic.getArrayData(src).add(srcOfs * 4);
final Extent size = Extent.fromIntZeroExtend(length * 4);
Unsafe.copy(srcPtr, start.add(dstPtr), size);
}
/**
* Sets a float at a given memory address
*
* @param memPtr
* @param value
*/
public void setFloat(int memPtr, float value) {
testMemPtr(memPtr, 4);
start.store(value, Offset.fromIntSignExtend(memPtr));
}
/**
* Sets multiple 32-bit floats at the given memory address
*
* @param src
* @param srcOfs
* @param dstPtr
* @param length
*/
public void setFloats(float[] src, int srcOfs, int dstPtr, int length) {
if (srcOfs < 0) {
throw new IndexOutOfBoundsException("srcOfs < 0");
}
if (length < 0) {
throw new IndexOutOfBoundsException("length < 0");
}
if (srcOfs + length > src.length) {
throw new IndexOutOfBoundsException("srcOfs + length > src.length");
}
testMemPtr(dstPtr, length * 4);
final Address srcPtr = VmMagic.getArrayData(src).add(srcOfs * 4);
final Extent size = Extent.fromIntZeroExtend(length * 4);
Unsafe.copy(srcPtr, start.add(dstPtr), size);
}
/**
* Sets a long at a given memory address
*
* @param memPtr
* @param value
*/
public void setLong(int memPtr, long value) {
testMemPtr(memPtr, 8);
start.store(value, Offset.fromIntSignExtend(memPtr));
}
/**
* Sets multiple 64-bit signed longs at the given memory address
*
* @param src
* @param srcOfs
* @param dstPtr
* @param length
*/
public void setLongs(long[] src, int srcOfs, int dstPtr, int length) {
if (srcOfs < 0) {
throw new IndexOutOfBoundsException("srcOfs < 0");
}
if (length < 0) {
throw new IndexOutOfBoundsException("length < 0");
}
if (srcOfs + length > src.length) {
throw new IndexOutOfBoundsException("srcOfs + length > src.length");
}
testMemPtr(dstPtr, length * 8);
final Address srcPtr = VmMagic.getArrayData(src).add(srcOfs * 8);
final Extent size = Extent.fromIntZeroExtend(length * 8);
Unsafe.copy(srcPtr, start.add(dstPtr), size);
}
/**
* Sets a double at a given memory address
*
* @param memPtr
* @param value
*/
public void setDouble(int memPtr, double value) {
testMemPtr(memPtr, 8);
start.store(value, Offset.fromIntSignExtend(memPtr));
}
/**
* Sets multiple 64-bit doubles at the given memory address
*
* @param src
* @param srcOfs
* @param dstPtr
* @param length
*/
public void setDoubles(double[] src, int srcOfs, int dstPtr, int length) {
if (srcOfs < 0) {
throw new IndexOutOfBoundsException("srcOfs < 0");
}
if (length < 0) {
throw new IndexOutOfBoundsException("length < 0");
}
if (srcOfs + length > src.length) {
throw new IndexOutOfBoundsException("srcOfs + length > src.length");
}
testMemPtr(dstPtr, length * 8);
final Address srcPtr = VmMagic.getArrayData(src).add(srcOfs * 8);
final Extent size = Extent.fromIntZeroExtend(length * 8);
Unsafe.copy(srcPtr, start.add(dstPtr), size);
}
/**
* Sets a Object at a given memory address
*
* @param memPtr
* @param value
*/
public void setObject(int memPtr, Object value) {
if (this.data != null) {
throw new SecurityException("Cannot set an Object in a byte-array");
}
testMemPtr(memPtr, 4);
start.store(ObjectReference.fromObject(value), Offset.fromIntSignExtend(memPtr));
}
/**
* Fill the memory at the given memory address with size times 0 bytes.
* <p/>
* memPtr must be VmObject.SLOT_SIZE aligned
* <p/>
* size % VmObject.SLOT_SIZE must be 0
*
* @param memPtr
* @param size
*/
public void clear(int memPtr, int size) {
testMemPtr(memPtr, size);
Unsafe.clear(start.add(Offset.fromIntZeroExtend(memPtr)), Extent.fromIntSignExtend(size));
}
/**
* (non-Javadoc)
*
* @see org.jnode.system.resource.MemoryResource#copy(int, int, int)
*/
public void copy(int srcMemPtr, int destMemPtr, int length) {
testMemPtr(srcMemPtr, length);
testMemPtr(destMemPtr, length);
final Extent size = Extent.fromIntZeroExtend(length);
Unsafe.copy(start.add(srcMemPtr), start.add(destMemPtr), size);
}
/**
* Remove a child from my list of children.
*
* @param child
*/
private synchronized void removeChild(MemoryResourceImpl child) {
this.children = (MemoryResourceImpl) remove(this.children, child);
}
/**
* Give up this resource. After this method has been called, the resource cannot be used
* anymore.
*/
public final void release() {
if (!this.released) {
// Mark released as true
this.released = true;
// Release all children
synchronized (this) {
while (this.children != null) {
this.children.release();
}
}
if (parent != null) {
// Remove me from parent.
parent.removeChild(this);
} else if (data == null) {
// Remove me from global memory resource list
synchronized (getClass()) {
resources = remove(resources, this);
}
}
}
}
protected final void testMemPtr(int memPtr, int size) {
if (released) {
throw new IndexOutOfBoundsException("MemoryResource is released");
}
final Word end = Word.fromIntZeroExtend(memPtr + size);
if ((memPtr < 0) || end.GT(this.size.toWord())) {
throw new IndexOutOfBoundsException("At " + memPtr + ", this.size=" + this.size.toLong());
}
}
/**
* Returns the size of this buffer in bytes.
*
* @return int
*/
public Extent getSize() {
return size;
}
/**
* Gets the address of the first byte of this buffer
*
* @return Address of first byte in buffer
*/
public Address getAddress() {
return start;
}
/**
* Compare to regions.
*
* @param otherRegion
* @return a negative integer, zero, or a positive integer as this object is less than, equal
* to, or greater than the specified region. If the regions overlap, 0 is returned.
*/
public int compareTo(Region otherRegion) {
final MemoryResourceImpl other = (MemoryResourceImpl) otherRegion;
if (this.end.LE(other.start)) {
// this < other
return -1;
}
if (this.start.GE(other.end)) {
// this > other
return 1;
}
// this overlaps other
return 0;
}
/**
* Compare this region with a given address.
* TODO that method appear unused. remove it ?
* @param address
* @return a negative integer, zero, or a positive integer as this region is less than,
* overlapping, or greater than the address.
*/
public int compareTo(Address address) {
if (this.end.LE(address)) {
// this < address
return -1;
}
if (this.start.GE(address)) {
// this > other
return 1;
}
// this overlaps address
return 0;
}
/**
* @param memPtr
* @param value
* @param count
* @see org.jnode.system.resource.MemoryResource#setByte(int, byte, int)
*/
public void setByte(int memPtr, byte value, int count) {
testMemPtr(memPtr, count);
Unsafe.setBytes(start.add(Offset.fromIntZeroExtend(memPtr)), value, count);
}
/**
* @param memPtr
* @param value
* @param count
* @see org.jnode.system.resource.MemoryResource#setChar(int, char, int)
*/
public void setChar(int memPtr, char value, int count) {
testMemPtr(memPtr, count * 2);
Unsafe.setChars(start.add(Offset.fromIntZeroExtend(memPtr)), value, count);
}
/**
* @param memPtr
* @param value
* @param count
* @see org.jnode.system.resource.MemoryResource#setDouble(int, double, int)
*/
public void setDouble(int memPtr, double value, int count) {
testMemPtr(memPtr, count * 8);
Unsafe.setDoubles(start.add(Offset.fromIntZeroExtend(memPtr)), value, count);
}
/**
* @param memPtr
* @param value
* @param count
* @see org.jnode.system.resource.MemoryResource#setFloat(int, float, int)
*/
public void setFloat(int memPtr, float value, int count) {
testMemPtr(memPtr, count * 4);
Unsafe.setFloats(start.add(Offset.fromIntZeroExtend(memPtr)), value, count);
}
/**
* @param memPtr
* @param value
* @param count
* @see org.jnode.system.resource.MemoryResource#setInt24(int, int, int)
*/
public void setInt24(int memPtr, int value, int count) {
testMemPtr(memPtr, count * 3);
Unsafe.setInts24(start.add(Offset.fromIntZeroExtend(memPtr)), value, count);
}
/**
* @param memPtr
* @param value
* @param count
* @see org.jnode.system.resource.MemoryResource#setInt(int, int, int)
*/
public void setInt(int memPtr, int value, int count) {
testMemPtr(memPtr, count * 4);
Unsafe.setInts(start.add(Offset.fromIntZeroExtend(memPtr)), value, count);
}
/**
* @param memPtr
* @param value
* @param count
* @see org.jnode.system.resource.MemoryResource#setLong(int, long, int)
*/
public void setLong(int memPtr, long value, int count) {
testMemPtr(memPtr, count * 8);
Unsafe.setLongs(start.add(Offset.fromIntZeroExtend(memPtr)), value, count);
}
/**
* @param memPtr
* @param value
* @param count
* @see org.jnode.system.resource.MemoryResource#setObject(int, java.lang.Object, int)
*/
public void setObject(int memPtr, Object value, int count) {
testMemPtr(memPtr, count * slotSize);
Unsafe.setObjects(start.add(Offset.fromIntZeroExtend(memPtr)), value, count);
}
/**
* @param memPtr
* @param value
* @param count
* @see org.jnode.system.resource.MemoryResource#setShort(int, short, int)
*/
public void setShort(int memPtr, short value, int count) {
testMemPtr(memPtr, count * 2);
Unsafe.setShorts(start.add(Offset.fromIntZeroExtend(memPtr)), value, count);
}
/**
* @param memPtr
* @param value
* @param count
* @see org.jnode.system.resource.MemoryResource#andByte(int, byte, int)
*/
public void andByte(int memPtr, byte value, int count) {
testMemPtr(memPtr, count);
Unsafe.andByte(start.add(Offset.fromIntZeroExtend(memPtr)), value, count);
}
/**
* @param memPtr
* @param value
* @param count
* @see org.jnode.system.resource.MemoryResource#andChar(int, char, int)
*/
public void andChar(int memPtr, char value, int count) {
testMemPtr(memPtr, count * 2);
Unsafe.andChar(start.add(Offset.fromIntZeroExtend(memPtr)), value, count);
}
/**
* @param memPtr
* @param value
* @param count
*/
public void andInt24(int memPtr, int value, int count) {
testMemPtr(memPtr, count * 3);
Unsafe.andInt24(start.add(Offset.fromIntZeroExtend(memPtr)), value, count);
}
/**
* @param memPtr
* @param value
* @param count
* @see org.jnode.system.resource.MemoryResource#andInt(int, int, int)
*/
public void andInt(int memPtr, int value, int count) {
testMemPtr(memPtr, count * 4);
Unsafe.andInt(start.add(Offset.fromIntZeroExtend(memPtr)), value, count);
}
/**
* @param memPtr
* @param value
* @param count
* @see org.jnode.system.resource.MemoryResource#andLong(int, long, int)
*/
public void andLong(int memPtr, long value, int count) {
testMemPtr(memPtr, count * 8);
Unsafe.andLong(start.add(Offset.fromIntZeroExtend(memPtr)), value, count);
}
/**
* @param memPtr
* @param value
* @param count
* @see org.jnode.system.resource.MemoryResource#andShort(int, short, int)
*/
public void andShort(int memPtr, short value, int count) {
testMemPtr(memPtr, count * 2);
Unsafe.andShort(start.add(Offset.fromIntZeroExtend(memPtr)), value, count);
}
/**
* @param memPtr
* @param value
* @param count
* @see org.jnode.system.resource.MemoryResource#orByte(int, byte, int)
*/
public void orByte(int memPtr, byte value, int count) {
testMemPtr(memPtr, count);
Unsafe.orByte(start.add(Offset.fromIntZeroExtend(memPtr)), value, count);
}
/**
* @param memPtr
* @param value
* @param count
* @see org.jnode.system.resource.MemoryResource#orChar(int, char, int)
*/
public void orChar(int memPtr, char value, int count) {
testMemPtr(memPtr, count * 2);
Unsafe.orChar(start.add(Offset.fromIntZeroExtend(memPtr)), value, count);
}
/**
* @param memPtr
* @param value
* @param count
*/
public void orInt24(int memPtr, int value, int count) {
testMemPtr(memPtr, count * 3);
Unsafe.orInt24(start.add(Offset.fromIntZeroExtend(memPtr)), value, count);
}
/**
* @param memPtr
* @param value
* @param count
* @see org.jnode.system.resource.MemoryResource#orInt(int, int, int)
*/
public void orInt(int memPtr, int value, int count) {
testMemPtr(memPtr, count * 4);
Unsafe.orInt(start.add(Offset.fromIntZeroExtend(memPtr)), value, count);
}
/**
* @param memPtr
* @param value
* @param count
* @see org.jnode.system.resource.MemoryResource#orLong(int, long, int)
*/
public void orLong(int memPtr, long value, int count) {
testMemPtr(memPtr, count * 8);
Unsafe.orLong(start.add(Offset.fromIntZeroExtend(memPtr)), value, count);
}
/**
* @param memPtr
* @param value
* @param count
* @see org.jnode.system.resource.MemoryResource#orShort(int, short, int)
*/
public void orShort(int memPtr, short value, int count) {
testMemPtr(memPtr, count * 2);
Unsafe.orShort(start.add(Offset.fromIntZeroExtend(memPtr)), value, count);
}
/**
* @param memPtr
* @param value
* @param count
* @see org.jnode.system.resource.MemoryResource#xorByte(int, byte, int)
*/
public void xorByte(int memPtr, byte value, int count) {
testMemPtr(memPtr, count);
Unsafe.xorByte(start.add(Offset.fromIntZeroExtend(memPtr)), value, count);
}
/**
* @param memPtr
* @param value
* @param count
* @see org.jnode.system.resource.MemoryResource#xorChar(int, char, int)
*/
public void xorChar(int memPtr, char value, int count) {
testMemPtr(memPtr, count * 2);
Unsafe.xorChar(start.add(Offset.fromIntZeroExtend(memPtr)), value, count);
}
/**
* @param memPtr
* @param value
* @param count
* @see org.jnode.system.resource.MemoryResource#xorInt(int, int, int)
*/
public void xorInt24(int memPtr, int value, int count) {
testMemPtr(memPtr, count * 3);
Unsafe.xorInt24(start.add(Offset.fromIntZeroExtend(memPtr)), value, count);
}
/**
* @param memPtr
* @param value
* @param count
* @see org.jnode.system.resource.MemoryResource#xorInt(int, int, int)
*/
public void xorInt(int memPtr, int value, int count) {
testMemPtr(memPtr, count * 4);
Unsafe.xorInt(start.add(Offset.fromIntZeroExtend(memPtr)), value, count);
}
/**
* @param memPtr
* @param value
* @param count
* @see org.jnode.system.resource.MemoryResource#xorLong(int, long, int)
*/
public void xorLong(int memPtr, long value, int count) {
testMemPtr(memPtr, count * 8);
Unsafe.xorLong(start.add(Offset.fromIntZeroExtend(memPtr)), value, count);
}
/**
* @param memPtr
* @param value
* @param count
* @see org.jnode.system.resource.MemoryResource#xorShort(int, short, int)
*/
public void xorShort(int memPtr, short value, int count) {
testMemPtr(memPtr, count * 2);
Unsafe.xorShort(start.add(Offset.fromIntZeroExtend(memPtr)), value, count);
}
/**
* Get a memory resource for a portion of this memory resources.
* The first area of this memory resource that fits the given size
* and it not claimed by any child resource is returned.
* If not large enought area if found, a ResourceNotFreeException is thrown.
* A child resource is always releases when the parent is released.
* A child resource can be released without releasing the parent.
*
* @param size Length of the returned resource in bytes.
* @param align
* @return a memory resource for a portion of this memory resources
* @throws IndexOutOfBoundsException
* @throws ResourceNotFreeException
*/
public MemoryResource claimChildResource(Extent size, int align)
throws IndexOutOfBoundsException, ResourceNotFreeException {
if (released) {
throw new IndexOutOfBoundsException("MemoryResource is released");
}
if (align <= 0) {
throw new IllegalArgumentException("Align must be >= 1");
}
Offset offset = Offset.zero();
final Word alignMask = Word.fromIntZeroExtend(align - 1);
while (true) {
final Address addr = this.start.add(offset);
final MemoryResourceImpl child = new MemoryResourceImpl(this, getOwner(), addr, size);
final MemoryResourceImpl existingChild = (MemoryResourceImpl) get(this.children, child);
if (existingChild == null) {
// We found a free region
this.children = (MemoryResourceImpl) add(this.children, child);
return child;
}
// We found an existing child, skip over that.
offset = existingChild.getOffset().add(existingChild.getSize());
// Align the new offset
if (!offset.toWord().and(alignMask).isZero()) {
offset = offset.toWord().add(alignMask).and(alignMask.not()).toOffset();
}
// Do we have space left?
if (offset.toWord().add(size).GT(this.size.toWord())) {
throw new ResourceNotFreeException();
}
}
}
/**
* Get a memory resource for a portion of this memory resources.
* The first area of this memory resource that fits the given size
* and it not claimed by any child resource is returned.
* If not large enought area if found, a ResourceNotFreeException is thrown.
* A child resource is always releases when the parent is released.
* A child resource can be released without releasing the parent.
*
* @param size Length of the returned resource in bytes.
* @param align Align of this boundary. Align must be a multiple of 2.
* @return a memory resource for a portion of this memory resources
* @throws IndexOutOfBoundsException
* @throws ResourceNotFreeException
*/
public MemoryResource claimChildResource(int size, int align)
throws IndexOutOfBoundsException, ResourceNotFreeException {
return claimChildResource(Extent.fromIntZeroExtend(size), align);
}
/**
* Get a memory resource for a portion of this memory resources.
* A child resource is always releases when the parent is released.
* A child resource can be released without releasing the parent.
*
* @param offset Offset relative to the start of this resource.
* @param size Length of the returned resource in bytes.
* @param allowOverlaps If true, overlapping child resources will be allowed,
* otherwise overlapping child resources will resulut in a ResourceNotFreeException.
* @return a memory resource for a portion of this memory resources
* @throws IndexOutOfBoundsException
* @throws ResourceNotFreeException
*/
public MemoryResource claimChildResource(Offset offset, Extent size, boolean allowOverlaps)
throws IndexOutOfBoundsException, ResourceNotFreeException {
if (released) {
throw new IndexOutOfBoundsException("MemoryResource is released");
}
if (offset.toWord().add(size).GT(this.size.toWord())) {
throw new IndexOutOfBoundsException("Offset + size > this.size");
}
final Address addr = this.start.add(offset);
final MemoryResourceImpl child = new MemoryResourceImpl(this, getOwner(), addr, size);
synchronized (this) {
// Re-test released flag
if (released) {
throw new IndexOutOfBoundsException("MemoryResource is released");
}
if (!allowOverlaps) {
if (!isFree(this.children, child)) {
throw new ResourceNotFreeException();
}
}
this.children = (MemoryResourceImpl) add(this.children, child);
}
return child;
}
/**
* Get a memory resource for a portion of this memory resources.
* A child resource is always releases when the parent is released.
* A child resource can be released without releasing the parent.
*
* @param offset Offset relative to the start of this resource.
* @param size Length of the returned resource in bytes.
* @param allowOverlaps If true, overlapping child resources will be allowed,
* otherwise overlapping child resources will resulut in a ResourceNotFreeException.
* @return a memory resource for a portion of this memory resource
* @throws IndexOutOfBoundsException
* @throws ResourceNotFreeException
*/
public MemoryResource claimChildResource(int offset, int size, boolean allowOverlaps)
throws IndexOutOfBoundsException, ResourceNotFreeException {
return claimChildResource(Offset.fromIntZeroExtend(offset), Extent.fromIntZeroExtend(size), allowOverlaps);
}
/**
* Creates a multi media memory resource wrapping this given memory resource.
*
* @return The created instance. This will never be null.
*/
public final MultiMediaMemoryResource asMultiMediaMemoryResource() {
final MultiMediaMemoryResourceImpl child;
child = ((BaseVmArchitecture) VmUtils.getVm().getArch()).createMultiMediaMemoryResource(this);
this.children = (MemoryResourceImpl) add(this.children, child);
return child;
}
/**
* Gets the parent resource if any.
*
* @return The parent resource, or null if this resource has no parent.
*/
public final Resource getParent() {
return parent;
}
/**
* Gets the offset relative to my parent.
* If this resource has no parent, the address of this buffer is returned.
*
* @return the offset relative to my parent or address of this buffer
*/
public final Offset getOffset() {
return this.offset;
}
}