10 #include <botan/internal/mem_pool.h>
11 #include <botan/internal/rounding.h>
12 #include <botan/mem_ops.h>
21 Pooling_Allocator::Memory_Block::Memory_Block(
void* buf)
23 buffer =
static_cast<byte*
>(buf);
25 buffer_end = buffer + (BLOCK_SIZE * BITMAP_SIZE);
31 bool Pooling_Allocator::Memory_Block::contains(
void* ptr,
34 return ((buffer <= ptr) &&
35 (buffer_end >= static_cast<byte*>(ptr) + length * BLOCK_SIZE));
43 if(n == 0 || n > BITMAP_SIZE)
57 bitmap_type mask = (
static_cast<bitmap_type
>(1) << n) - 1;
65 if((bitmap & mask) == 0)
75 return buffer + offset * BLOCK_SIZE;
81 void Pooling_Allocator::Memory_Block::free(
void* ptr,
size_t blocks)
83 clear_mem(static_cast<byte*>(ptr), blocks * BLOCK_SIZE);
85 const size_t offset = (
static_cast<byte*
>(ptr) - buffer) / BLOCK_SIZE;
87 if(offset == 0 && blocks == BITMAP_SIZE)
91 for(
size_t j = 0; j != blocks; ++j)
92 bitmap &= ~(static_cast<bitmap_type>(1) << (j+offset));
101 last_used = blocks.begin();
111 throw Invalid_State(
"Pooling_Allocator: Never released memory");
123 for(
size_t j = 0; j != allocated.size(); ++j)
124 dealloc_block(allocated[j].first, allocated[j].second);
133 const size_t BITMAP_SIZE = Memory_Block::bitmap_size();
138 if(n <= BITMAP_SIZE * BLOCK_SIZE)
140 const size_t block_no =
round_up(n, BLOCK_SIZE) / BLOCK_SIZE;
142 byte* mem = allocate_blocks(block_no);
146 get_more_core(BOTAN_MEM_POOL_CHUNK_SIZE);
148 mem = allocate_blocks(block_no);
155 void* new_buf = alloc_block(n);
167 const size_t BITMAP_SIZE = Memory_Block::bitmap_size();
170 if(ptr == 0 || n == 0)
175 if(n > BITMAP_SIZE * BLOCK_SIZE)
176 dealloc_block(ptr, n);
179 const size_t block_no =
round_up(n, BLOCK_SIZE) / BLOCK_SIZE;
181 std::vector<Memory_Block>::iterator i =
182 std::lower_bound(blocks.begin(), blocks.end(), Memory_Block(ptr));
184 if(i == blocks.end() || !i->contains(ptr, block_no))
185 throw Invalid_State(
"Pointer released to the wrong allocator");
187 i->free(ptr, block_no);
194 byte* Pooling_Allocator::allocate_blocks(
size_t n)
199 std::vector<Memory_Block>::iterator i = last_used;
203 byte* mem = i->alloc(n);
211 if(i == blocks.end())
214 while(i != last_used);
222 void Pooling_Allocator::get_more_core(
size_t in_bytes)
224 const size_t BITMAP_SIZE = Memory_Block::bitmap_size();
227 const size_t TOTAL_BLOCK_SIZE = BLOCK_SIZE * BITMAP_SIZE;
230 in_bytes = std::min<size_t>(in_bytes, 1024 * 1024);
232 const size_t in_blocks =
round_up(in_bytes, BLOCK_SIZE) / TOTAL_BLOCK_SIZE;
233 const size_t to_allocate = in_blocks * TOTAL_BLOCK_SIZE;
235 void* ptr = alloc_block(to_allocate);
237 throw Memory_Exhaustion();
239 allocated.push_back(std::make_pair(ptr, to_allocate));
241 for(
size_t j = 0; j != in_blocks; ++j)
243 byte* byte_ptr =
static_cast<byte*
>(ptr);
244 blocks.push_back(Memory_Block(byte_ptr + j * TOTAL_BLOCK_SIZE));
247 std::sort(blocks.begin(), blocks.end());
248 last_used = std::lower_bound(blocks.begin(), blocks.end(),
void deallocate(void *, size_t)
void clear_mem(T *ptr, size_t n)
Pooling_Allocator(Mutex *mutex)
T round_up(T n, T align_to)