Package org.jnode.vm

Source Code of org.jnode.vm.MemoryResourceImpl

/*
* $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;
    }
}
TOP

Related Classes of org.jnode.vm.MemoryResourceImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.