Package org.jnode.vm

Source Code of org.jnode.vm.AllocationBitmap

/*
* $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 org.jnode.annotation.MagicPermission;
import org.jnode.annotation.Uninterruptible;
import org.jnode.vm.facade.VmUtils;
import org.jnode.vm.scheduler.VmThread;
import org.vmmagic.unboxed.Address;
import org.vmmagic.unboxed.Extent;
import org.vmmagic.unboxed.Word;

/**
* A bitmap that stores its bits in a raw memory region.
*
* @author Ewout Prangsma (epr@users.sourceforge.net)
*/
@MagicPermission
@Uninterruptible
public class AllocationBitmap {

    /**
     * Inclusive start address of the bitmap memory region
     */
    private Address start = Address.zero();

    /**
     * Exclusive end address of the bitmap memory region
     */
    private Address end = Address.zero();

    /**
     * Number of bits in the bitmap
     */
    private Word bits;

    /**
     * Lock address for access to the bits in this bitmap
     */
    private Address lock;

    /**
     * Address of bits data
     */
    private Address bitmap;

    /**
     * Size of the bitmap memory region
     */
    private Extent size;

    /**
     * Number of allocated bits
     */
    private Word allocatedBits = Word.zero();

    /**
     * Number of next allocatable bit
     */
    private Word nextBitNr = Word.zero();

    /**
     * Initialize this instance.
     */
    public AllocationBitmap() {
        // Nothing here
    }

    /**
     * Initialize this bitmap.
     *
     * @param start
     * @param bits
     */
    public final void initialize(Address start, Word bits) {
        // Size of the lock (we only use an int)
        final Extent lockSize = Extent.fromIntZeroExtend(VmUtils.getVm().getArch()
            .getReferenceSize());

        // Create a lock and actual bitmap
        final Extent rawBitmapSize = bits.rshl(3).toExtent();
        final Extent bitmapSize = rawBitmapSize.toWord().add(lockSize)
            .toExtent();

        this.start = start;
        this.end = start.add(bitmapSize);
        this.bits = bits;
        this.lock = start;
        this.bitmap = start.add(lockSize);
        this.size = bitmapSize;
        this.allocatedBits = Word.zero();
        this.nextBitNr = Word.zero();

        // Clear the total bitmap + lock region
        Unsafe.clear(start, bitmapSize);
    }

    /**
     * Gets the size of the memory region occupied by this bitmap.
     *
     * @return the size as an Extent.
     */
    public final Extent getSize() {
        return size;
    }

    /**
     * Allocate a new series of bits.
     *
     * @param noBits
     * @return The bit index of the start of the bit series, or Word.max() when
     *         not enough free bits are available.
     */
    public final Word allocateBits(Word noBits) {
        lock();
        try {
            // Find a large enough series of bits
            final Word nr = findFreeBits(noBits);
            if (nr.isMax()) {
                return nr;
            }
            // Mark all blocks as in use
            for (Word i = Word.zero(); i.LT(noBits); i = i.add(1)) {
                set(nr.add(i), true);
            }
            // Return the address of block "nr".
            allocatedBits = allocatedBits.add(noBits);
            nextBitNr = nr.add(noBits);
            return nr;
        } finally {
            unlock();
        }
    }

    /**
     * Free a previously allocated series of bits.
     *
     * @param bit    The bit number as returned by allocateBits.
     * @param noBits The size of the bit series as given to allocateBits.
     */
    public final void freeBits(Word bit, Word noBits) {
        lock();
        try {
            // Mark all blocks as free
            for (Word i = Word.zero(); i.LT(noBits); i = i.add(1)) {
                set(bit.add(i), false);
            }
            allocatedBits = allocatedBits.sub(noBits);
            if (bit.LT(nextBitNr)) {
                nextBitNr = bit;
            }
        } finally {
            unlock();
        }
    }

    /**
     * Mark a series of bits as set.
     *
     * @param bit    The start of the series
     * @param noBits The number of bits in the series
     */
    public final void setBits(Word bit, Word noBits) {
        if (bit.add(noBits).GT(this.bits)) {
            throw new IndexOutOfBoundsException();
        }
        lock();
        try {
            // Mark all bits as set
            for (Word i = Word.zero(); i.LT(noBits); i = i.add(1)) {
                set(bit.add(i), true);
            }
            allocatedBits = allocatedBits.add(noBits);
        } finally {
            unlock();
        }
    }

    /**
     * Find the first free bits that is following by freeBits-1 free bits.
     *
     * @param freeBits
     * @return The bit number of the first block, or Word.max() if not found.
     */
    private final Word findFreeBits(Word freeBits) {
        final Word max = bits;
        Word nr = nextBitNr;
        while (nr.LT(max)) {
            boolean inUse = false;
            Word i;
            for (i = Word.zero(); i.LT(freeBits) && (!inUse); i = i.add(1)) {
                inUse |= isSet(nr.add(i));
            }
            if (!inUse) {
                // We found it
                return nr;
            } else {
                // Unsafe.debug("nr"); Unsafe.debug(nr);
                // Unsafe.debug("i"); Unsafe.debug(i);
                // We came across an used block
                nr = nr.add(i).add(1);
            }
        }
        // Unsafe.debug("ret -1"); Unsafe.die();
        return Word.max();
    }

    /**
     * Test if a given bit is set.
     *
     * @param bit the bit to be tested
     * @return {@link true} if the bit is set, {@code false} otherwise.
     */
    private final boolean isSet(Word bit) {
        final Word offset = bit.rshl(3); // we still need a byte offset
        final int mask = (1 << bit.and(Word.fromIntZeroExtend(7)).toInt());
        final Address ptr = bitmap.add(offset);
        final int v = ptr.loadByte() & 0xFF;
        return ((v & mask) == mask);
    }

    /**
     * Set/Reset a given bit.
     *
     * @param bit the bit to be set or reset
     * @param value the new value for the bit
     */
    private final void set(Word bit, boolean value) {
        final Word offset = bit.rshl(3); // we still need a byte offset
        final int mask = (1 << bit.and(Word.fromIntZeroExtend(7)).toInt());
        // final int mask = (1 << blockNr);
        final Address ptr = bitmap.add(offset);
        int v = ptr.loadByte();
        if (value) {
            v |= mask;
        } else {
            v &= ~mask;
        }
        ptr.store((byte) v);
    }

    /**
     * Claim an exclusive access lock the Bitmap data structures. This is done without using java
     * monitorenter/exit instructions, since they may need a memory allocation.
     */
    private final void lock() {
        while (!lock.attempt(0, 1)) {
            // Unsafe.debug(lock.loadInt());
            VmThread.yield();
        }
    }

    /**
     * Release the exclusive access lock to the Bitmap data structures.  Note that no attempt
     * is made to check that the lock is owned by the current thread.
     */
    private final void unlock() {
        lock.store((int) 0);
    }
}
TOP

Related Classes of org.jnode.vm.AllocationBitmap

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.