1 /* 2 * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * - Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * - Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * - Neither the name of Oracle nor the names of its 16 * contributors may be used to endorse or promote products derived 17 * from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 20 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * This source code is provided to illustrate the usage of a given feature 34 * or technique and has been deliberately simplified. Additional steps 35 * required for a production-quality application, such as security checks, 36 * input validation and proper error handling, might not be present in 37 * this sample code. 38 */ 39 40 41 /* Allocations from large blocks, no individual free's */ 42 43 #include "hprof.h" 44 45 /* 46 * This file contains some allocation code that allows you 47 * to have space allocated via larger blocks of space. 48 * The only free allowed is of all the blocks and all the elements. 49 * Elements can be of different alignments and fixed or variable sized. 50 * The space allocated never moves. 51 * 52 */ 53 54 /* Get the real size allocated based on alignment and bytes needed */ 55 static int 56 real_size(int alignment, int nbytes) 57 { 58 if ( alignment > 1 ) { 59 int wasted; 60 61 wasted = alignment - ( nbytes % alignment ); 62 if ( wasted != alignment ) { 63 nbytes += wasted; 64 } 65 } 66 return nbytes; 67 } 68 69 /* Add a new current_block to the Blocks* chain, adjust size if nbytes big. */ 70 static void 71 add_block(Blocks *blocks, int nbytes) 72 { 73 int header_size; 74 int block_size; 75 BlockHeader *block_header; 76 77 HPROF_ASSERT(blocks!=NULL); 78 HPROF_ASSERT(nbytes>0); 79 80 header_size = real_size(blocks->alignment, sizeof(BlockHeader)); 81 block_size = blocks->elem_size*blocks->population; 82 if ( nbytes > block_size ) { 83 block_size = real_size(blocks->alignment, nbytes); 84 } 85 block_header = (BlockHeader*)HPROF_MALLOC(block_size+header_size); 86 block_header->next = NULL; 87 block_header->bytes_left = block_size; 88 block_header->next_pos = header_size; 89 90 /* Link in new block */ 91 if ( blocks->current_block != NULL ) { 92 blocks->current_block->next = block_header; 93 } 94 blocks->current_block = block_header; 95 if ( blocks->first_block == NULL ) { 96 blocks->first_block = block_header; 97 } 98 } 99 100 /* Initialize a new Blocks */ 101 Blocks * 102 blocks_init(int alignment, int elem_size, int population) 103 { 104 Blocks *blocks; 105 106 HPROF_ASSERT(alignment>0); 107 HPROF_ASSERT(elem_size>0); 108 HPROF_ASSERT(population>0); 109 110 blocks = (Blocks*)HPROF_MALLOC(sizeof(Blocks)); 111 blocks->alignment = alignment; 112 blocks->elem_size = elem_size; 113 blocks->population = population; 114 blocks->first_block = NULL; 115 blocks->current_block = NULL; 116 return blocks; 117 } 118 119 /* Allocate bytes from a Blocks area. */ 120 void * 121 blocks_alloc(Blocks *blocks, int nbytes) 122 { 123 BlockHeader *block; 124 int pos; 125 void *ptr; 126 127 HPROF_ASSERT(blocks!=NULL); 128 HPROF_ASSERT(nbytes>=0); 129 if ( nbytes == 0 ) { 130 return NULL; 131 } 132 133 block = blocks->current_block; 134 nbytes = real_size(blocks->alignment, nbytes); 135 if ( block == NULL || block->bytes_left < nbytes ) { 136 add_block(blocks, nbytes); 137 block = blocks->current_block; 138 } 139 pos = block->next_pos; 140 ptr = (void*)(((char*)block)+pos); 141 block->next_pos += nbytes; 142 block->bytes_left -= nbytes; 143 return ptr; 144 } 145 146 /* Terminate the Blocks */ 147 void 148 blocks_term(Blocks *blocks) 149 { 150 BlockHeader *block; 151 152 HPROF_ASSERT(blocks!=NULL); 153 154 block = blocks->first_block; 155 while ( block != NULL ) { 156 BlockHeader *next_block; 157 158 next_block = block->next; 159 HPROF_FREE(block); 160 block = next_block; 161 } 162 HPROF_FREE(blocks); 163 }