00001 /** @file 00002 00003 A brief file description 00004 00005 @section license License 00006 00007 Licensed to the Apache Software Foundation (ASF) under one 00008 or more contributor license agreements. See the NOTICE file 00009 distributed with this work for additional information 00010 regarding copyright ownership. The ASF licenses this file 00011 to you under the Apache License, Version 2.0 (the 00012 "License"); you may not use this file except in compliance 00013 with the License. You may obtain a copy of the License at 00014 00015 http://www.apache.org/licenses/LICENSE-2.0 00016 00017 Unless required by applicable law or agreed to in writing, software 00018 distributed under the License is distributed on an "AS IS" BASIS, 00019 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00020 See the License for the specific language governing permissions and 00021 limitations under the License. 00022 */ 00023 00024 #include "libts.h" 00025 #include <assert.h> 00026 #include <string.h> 00027 00028 00029 #define DEFAULT_ALLOC_SIZE 1024 00030 #define DEFAULT_BLOCK_SIZE (DEFAULT_ALLOC_SIZE - (sizeof (ArenaBlock) - 8)) 00031 00032 00033 static Allocator defaultSizeArenaBlock("ArenaBlock", DEFAULT_ALLOC_SIZE); 00034 00035 00036 /*------------------------------------------------------------------------- 00037 -------------------------------------------------------------------------*/ 00038 00039 static inline ArenaBlock * 00040 blk_alloc(int size) 00041 { 00042 ArenaBlock *blk; 00043 00044 if (size == DEFAULT_BLOCK_SIZE) { 00045 blk = (ArenaBlock *) defaultSizeArenaBlock.alloc_void(); 00046 } else { 00047 blk = (ArenaBlock *)ats_malloc(size + sizeof(ArenaBlock) - 8); 00048 } 00049 00050 blk->next = NULL; 00051 blk->m_heap_end = &blk->data[size]; 00052 blk->m_water_level = &blk->data[0]; 00053 00054 return blk; 00055 } 00056 00057 /*------------------------------------------------------------------------- 00058 -------------------------------------------------------------------------*/ 00059 00060 static inline void 00061 blk_free(ArenaBlock * blk) 00062 { 00063 int size; 00064 00065 size = blk->m_heap_end - &blk->data[0]; 00066 if (size == DEFAULT_BLOCK_SIZE) { 00067 defaultSizeArenaBlock.free_void(blk); 00068 } else { 00069 ats_free(blk); 00070 } 00071 } 00072 00073 00074 /*------------------------------------------------------------------------- 00075 -------------------------------------------------------------------------*/ 00076 00077 static void * 00078 block_alloc(ArenaBlock * block, size_t size, size_t alignment) 00079 { 00080 char *mem; 00081 00082 mem = block->m_water_level; 00083 if (((size_t) mem) & (alignment - 1)) { 00084 mem += (alignment - ((size_t) mem)) & (alignment - 1); 00085 } 00086 00087 if ((block->m_heap_end >= mem) && (((size_t) block->m_heap_end - (size_t) mem) >= size)) { 00088 block->m_water_level = mem + size; 00089 return mem; 00090 } 00091 00092 return NULL; 00093 } 00094 00095 void * 00096 Arena::alloc(size_t size, size_t alignment) 00097 { 00098 ArenaBlock *b; 00099 unsigned int block_size; 00100 void *mem; 00101 00102 ink_assert((alignment & (alignment - 1)) == 0); 00103 00104 b = m_blocks; 00105 while (b) { 00106 mem = block_alloc(b, size, alignment); 00107 if (mem) { 00108 return mem; 00109 } 00110 b = b->next; 00111 } 00112 00113 block_size = (unsigned int) (size * 1.5); 00114 if (block_size < DEFAULT_BLOCK_SIZE) { 00115 block_size = DEFAULT_BLOCK_SIZE; 00116 } 00117 00118 b = blk_alloc(block_size); 00119 b->next = m_blocks; 00120 m_blocks = b; 00121 00122 mem = block_alloc(b, size, alignment); 00123 return mem; 00124 } 00125 00126 /*------------------------------------------------------------------------- 00127 -------------------------------------------------------------------------*/ 00128 00129 void 00130 Arena::free(void *mem, size_t size) 00131 { 00132 if (m_blocks) { 00133 ArenaBlock *b; 00134 00135 b = m_blocks; 00136 while (b->next) { 00137 b = b->next; 00138 } 00139 00140 if (b->m_water_level == ((char *) mem + size)) { 00141 b->m_water_level = (char *) mem; 00142 } 00143 } 00144 } 00145 00146 /*------------------------------------------------------------------------- 00147 -------------------------------------------------------------------------*/ 00148 00149 void 00150 Arena::reset() 00151 { 00152 ArenaBlock *b; 00153 00154 while (m_blocks) { 00155 b = m_blocks->next; 00156 blk_free(m_blocks); 00157 m_blocks = b; 00158 } 00159 ink_assert(m_blocks == NULL); 00160 }