Beispiel #1
0
        /// <summary>
        /// Releases the memory back in the buddy pool.
        /// </summary>
        /// <param name="offset"></param>
        public void Release(int offset)
        {
            // Do not do anything if disposed
            if (this.Disposed)
            {
                return;
            }

            // Convert the offset
            int index = offset / BuddyBlock.Size;

            if (index < 0 || index >= this.NumberOfBlocks)
            {
                throw new ArgumentOutOfRangeException("The specified offset was not found in the pool.");
            }

            if (this.Metadata == null)
            {
                return;
            }

            // Smaller lock, starting where we actually touch the pool
            lock (this.Lock)
            {
                // Get the block address
                BuddyBlock block = this.Metadata[index];

                // Decrement the segments
                if (block.Status > BuddyBlockStatus.Reserved)
                {
                    block.Status--;
                    return;
                }

                block.Status = BuddyBlockStatus.Available;

                //BuddyBlock* ptr;
                //for (ptr = block; ptr->Power < this.NumberOfPowers; (ptr->Power)++)
                BuddyBlock ptr = block;
                for (int i = ptr.Power; i < this.NumberOfPowers; i++)
                {
                    // Instead of hitting  this.GetBuddy(ptr), we simply manually inline this
                    BuddyBlock buddy = this.Metadata[((ptr.Offset ^ (1 << (ptr.Power))) / BuddyBlock.Size)];
                    if (buddy.Status == BuddyBlockStatus.Reserved || buddy.Power != ptr.Power)
                    {
                        break;
                    }

                    Unlink(buddy);

                    //if (buddy < ptr)
                    if (buddy.Offset < ptr.Offset)
                    {
                        ptr = buddy;
                    }
                }
                InsertAfter(this.Sentinel[ptr.Power], ptr);
            }
        }
Beispiel #2
0
 private void InsertAfter(BuddyBlock src, BuddyBlock block)
 {
     block.Next     = src.Next;
     block.Previous = src;
     if (src.Next != null)
     {
         src.Next.Previous = block;
     }
     src.Next = block;
 }
Beispiel #3
0
 private void Unlink(BuddyBlock block)
 {
     if (block.Next != null)
     {
         block.Next.Previous = block.Previous;
     }
     if (block.Previous != null)
     {
         block.Previous.Next = block.Next;
     }
     block.Next = block.Previous = block;
 }
Beispiel #4
0
        /// <summary>
        /// Returns a pointer to the region of memory that is allocated.
        /// </summary>
        /// <param name="size">An integer-valued argument which specifies the size of storage area required.</param>
        /// <returns>A pointer to the region of memory that is allocated.</returns>
        public int Acquire(int size)
        {
            lock (this.Lock)
            {
                int kPrime = Log2Ceil(size > BuddyBlock.Size ? size : BuddyBlock.Size);
                int i      = kPrime;

                while (i <= this.NumberOfPowers && (this.Sentinel[i]).Next == (this.Sentinel[i]))
                {
                    ++i;
                }

                if (i > this.NumberOfPowers)
                {
                    int powers = this.NumberOfPowers;
                    int blocks = this.NumberOfBlocks;

                    // Resize instead, with a maximum check
                    this.Resize(++this.NumberOfPowers);

                    // Set the sentinel to the newly allocated space
                    BuddyBlock head = this.Metadata[blocks];
                    head.Status = BuddyBlockStatus.Available;
                    head.Power  = powers;
                    InsertAfter(this.Sentinel[powers], head);

                    // Search again
                    return(Acquire(size));
                }

                BuddyBlock block = this.Sentinel[i].Next;
                Unlink(block);
                while (block.Power > kPrime)
                {
                    block.Power--;

                    // Instead of hitting this.GetBuddy(block), we simply manually inline it
                    var buddy = this.Metadata[((block.Offset ^ (1 << (block.Power))) / BuddyBlock.Size)];
                    buddy.Status = BuddyBlockStatus.Available;
                    buddy.Power  = block.Power;

                    InsertAfter(this.Sentinel[buddy.Power], buddy);
                }

                block.Status = BuddyBlockStatus.Reserved;

                // Return the offset of the allocated block
                return(block.Offset);
            }
        }
Beispiel #5
0
 /// <summary>
 /// Gets a buddy of a given block.
 /// </summary>
 /// <param name="block">The block to get a buddy for.</param>
 /// <returns>The pointer to the buddy.</returns>
 private BuddyBlock GetBuddy(BuddyBlock block)
 {
     return(this.Metadata[((block.Offset ^ (1 << (block.Power))) / BuddyBlock.Size)]);
 }