/*
 * Copyright 2004 Sun Microsystems, Inc.  All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/* Allocations from large blocks, no individual free's */

#include "hprof.h"

/*
 * This file contains some allocation code that allows you
 *   to have space allocated via larger blocks of space.
 * The only free allowed is of all the blocks and all the elements.
 * Elements can be of different alignments and fixed or variable sized.
 * The space allocated never moves.
 *
 */

/* Get the real size allocated based on alignment and bytes needed */
static int
real_size(int alignment, int nbytes)
{
    if ( alignment > 1 ) {
        int wasted;

        wasted = alignment - ( nbytes % alignment );
        if ( wasted != alignment ) {
            nbytes += wasted;
        }
    }
    return nbytes;
}

/* Add a new current_block to the Blocks* chain, adjust size if nbytes big. */
static void
add_block(Blocks *blocks, int nbytes)
{
    int header_size;
    int block_size;
    BlockHeader *block_header;

    HPROF_ASSERT(blocks!=NULL);
    HPROF_ASSERT(nbytes>0);

    header_size          = real_size(blocks->alignment, sizeof(BlockHeader));
    block_size           = blocks->elem_size*blocks->population;
    if ( nbytes > block_size ) {
        block_size = real_size(blocks->alignment, nbytes);
    }
    block_header         = (BlockHeader*)HPROF_MALLOC(block_size+header_size);
    block_header->next   = NULL;
    block_header->bytes_left = block_size;
    block_header->next_pos   = header_size;

    /* Link in new block */
    if ( blocks->current_block != NULL ) {
        blocks->current_block->next = block_header;
    }
    blocks->current_block = block_header;
    if ( blocks->first_block == NULL ) {
        blocks->first_block = block_header;
    }
}

/* Initialize a new Blocks */
Blocks *
blocks_init(int alignment, int elem_size, int population)
{
    Blocks *blocks;

    HPROF_ASSERT(alignment>0);
    HPROF_ASSERT(elem_size>0);
    HPROF_ASSERT(population>0);

    blocks                = (Blocks*)HPROF_MALLOC(sizeof(Blocks));
    blocks->alignment     = alignment;
    blocks->elem_size     = elem_size;
    blocks->population    = population;
    blocks->first_block   = NULL;
    blocks->current_block = NULL;
    return blocks;
}

/* Allocate bytes from a Blocks area. */
void *
blocks_alloc(Blocks *blocks, int nbytes)
{
    BlockHeader *block;
    int   pos;
    void *ptr;

    HPROF_ASSERT(blocks!=NULL);
    HPROF_ASSERT(nbytes>=0);
    if ( nbytes == 0 ) {
        return NULL;
    }

    block = blocks->current_block;
    nbytes = real_size(blocks->alignment, nbytes);
    if ( block == NULL || block->bytes_left < nbytes ) {
        add_block(blocks, nbytes);
        block = blocks->current_block;
    }
    pos = block->next_pos;
    ptr = (void*)(((char*)block)+pos);
    block->next_pos   += nbytes;
    block->bytes_left -= nbytes;
    return ptr;
}

/* Terminate the Blocks */
void
blocks_term(Blocks *blocks)
{
    BlockHeader *block;

    HPROF_ASSERT(blocks!=NULL);

    block = blocks->first_block;
    while ( block != NULL ) {
        BlockHeader *next_block;

        next_block = block->next;
        HPROF_FREE(block);
        block = next_block;
    }
    HPROF_FREE(blocks);
}
