8 #include <botan/locking_allocator.h>
9 #include <botan/internal/os_utils.h>
10 #include <botan/mem_ops.h>
14 #include <botan/mutex.h>
20 bool ptr_in_pool(
const void* pool_ptr,
size_t poolsize,
21 const void* buf_ptr,
size_t bufsize)
23 const uintptr_t pool =
reinterpret_cast<uintptr_t
>(pool_ptr);
24 const uintptr_t buf =
reinterpret_cast<uintptr_t
>(buf_ptr);
26 if(buf < pool || buf >= pool + poolsize)
30 "Pointer does not partially overlap pool");
35 size_t padding_for_alignment(
size_t offset,
size_t desired_alignment)
37 size_t mod = offset % desired_alignment;
40 return desired_alignment - mod;
50 const size_t n = num_elems * elem_size;
51 const size_t alignment = 16;
53 if(n / elem_size != num_elems)
58 if(n < BOTAN_MLOCK_ALLOCATOR_MIN_ALLOCATION || n > BOTAN_MLOCK_ALLOCATOR_MAX_ALLOCATION)
61 lock_guard_type<mutex_type> lock(m_mutex);
63 auto best_fit = m_freelist.end();
65 for(
auto i = m_freelist.begin(); i != m_freelist.end(); ++i)
68 if(i->second == n && (i->first % alignment) == 0)
70 const size_t offset = i->first;
74 BOTAN_ASSERT((reinterpret_cast<size_t>(m_pool) + offset) % alignment == 0,
75 "Returning correctly aligned pointer");
77 return m_pool + offset;
80 if((i->second >= (n + padding_for_alignment(i->first, alignment)) &&
81 ((best_fit == m_freelist.end()) || (best_fit->second > i->second))))
87 if(best_fit != m_freelist.end())
89 const size_t offset = best_fit->first;
91 const size_t alignment_padding = padding_for_alignment(offset, alignment);
93 best_fit->first += n + alignment_padding;
94 best_fit->second -= n + alignment_padding;
106 if(best_fit->second == 0)
108 best_fit->first = offset;
109 best_fit->second = alignment_padding;
112 m_freelist.insert(best_fit, std::make_pair(offset, alignment_padding));
115 clear_mem(m_pool + offset + alignment_padding, n);
117 BOTAN_ASSERT((reinterpret_cast<size_t>(m_pool) + offset + alignment_padding) % alignment == 0,
118 "Returning correctly aligned pointer");
120 return m_pool + offset + alignment_padding;
131 size_t n = num_elems * elem_size;
138 "No overflow in deallocation");
140 if(!ptr_in_pool(m_pool, m_poolsize, p, n))
143 std::memset(p, 0, n);
145 lock_guard_type<mutex_type> lock(m_mutex);
147 const size_t start =
static_cast<uint8_t*
>(p) - m_pool;
149 auto comp = [](std::pair<size_t, size_t> x, std::pair<size_t, size_t> y){
return x.first < y.first; };
151 auto i = std::lower_bound(m_freelist.begin(), m_freelist.end(),
152 std::make_pair(start, 0), comp);
155 if(i != m_freelist.end() && start + n == i->first)
163 if(i != m_freelist.begin())
165 auto prev = std::prev(i);
167 if(prev->first + prev->second == start)
177 prev->second += i->second;
184 m_freelist.insert(i, std::make_pair(start, n));
189 mlock_allocator::mlock_allocator()
203 if(m_pool !=
nullptr)
205 m_poolsize = mem_to_lock;
206 m_freelist.push_back(std::make_pair(0, m_poolsize));
211 mlock_allocator::~mlock_allocator()
void secure_scrub_memory(void *ptr, size_t n)
static mlock_allocator & instance()
void clear_mem(T *ptr, size_t n)
void * allocate_locked_pages(size_t length)
bool deallocate(void *p, size_t num_elems, size_t elem_size)
void * allocate(size_t num_elems, size_t elem_size)
size_t get_memory_locking_limit()
#define BOTAN_ASSERT(expr, assertion_made)
void free_locked_pages(void *ptr, size_t length)