LMMS
Loading...
Searching...
No Matches
Allocator.cpp
Go to the documentation of this file.
1/*
2 ZynAddSubFX - a software synthesizer
3
4 Allocator.cpp - RT-Safe Memory Allocator
5 Copyright (C) 2016 Mark McCurry
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
11*/
12#include <cstddef>
13#include <cstdlib>
14#include <cassert>
15#include <utility>
16#include <cstdio>
17#include "tlsf/tlsf.h"
18#include "Allocator.h"
19
20namespace zyncarla {
21
22//Used for dummy allocations
25//recursive type class to avoid void *v = *(void**)v style casting
26struct next_t
27{
29 size_t pool_size;
30};
31
32void *data(next_t *n)
33{
34 return n+sizeof(next_t);
35}
36
37
39{
40 void *tlsf = 0;
41
42 //singly linked list of memory pools
43 //XXX this may violate alignment on some platforms if malloc doesn't return
44 //nice values
46 unsigned long long totalAlloced = 0;
47};
48
50{
51 impl = new AllocatorImpl;
52 size_t default_size = 10*1024*1024;
53 impl->pools = (next_t*)malloc(default_size);
54 impl->pools->next = 0x0;
55 impl->pools->pool_size = default_size;
56 size_t off = tlsf_size() + tlsf_pool_overhead() + sizeof(next_t);
57 //printf("Generated Memory Pool with '%p'\n", impl->pools);
58 impl->tlsf = tlsf_create_with_pool(((char*)impl->pools)+off, default_size-2*off);
59 //printf("Allocator(%p)\n", impl);
60}
61
63{
64 next_t *n = impl->pools;
65 while(n) {
66 next_t *nn = n->next;
67 free(n);
68 n = nn;
69 }
70 delete impl;
71}
72
73void *AllocatorClass::alloc_mem(size_t mem_size)
74{
75 impl->totalAlloced += mem_size;
76 void *mem = tlsf_malloc(impl->tlsf, mem_size);
77 //printf("Allocator.malloc(%p, %d) = %p\n", impl, mem_size, mem);
78 //void *mem = malloc(mem_size);
79 //printf("Allocator result = %p\n", mem);
80 return mem;
81}
83{
84 //printf("dealloc_mem(%d)\n", tlsf_block_size(memory));
85 tlsf_free(impl->tlsf, memory);
86 //free(memory);
87}
88
89bool AllocatorClass::lowMemory(unsigned n, size_t chunk_size) const
90{
91 //This should stay on the stack
92 void *buf[n];
93 for(unsigned i=0; i<n; ++i)
94 buf[i] = tlsf_malloc(impl->tlsf, chunk_size);
95 bool outOfMem = false;
96 for(unsigned i=0; i<n; ++i)
97 outOfMem |= (buf[i] == nullptr);
98 for(unsigned i=0; i<n; ++i)
99 if(buf[i])
100 tlsf_free(impl->tlsf, buf[i]);
101
102 return outOfMem;
103}
104
105
106void AllocatorClass::addMemory(void *v, size_t mem_size)
107{
108 next_t *n = impl->pools;
109 while(n->next) n = n->next;
110 n->next = (next_t*)v;
111 n->next->next = 0x0;
112 n->next->pool_size = mem_size;
113 //printf("Inserting '%p'\n", v);
114 off_t off = sizeof(next_t) + tlsf_pool_overhead();
115 void *result =
116 tlsf_add_pool(impl->tlsf, ((char*)n->next)+off,
117 //0x0eadbeef);
118 mem_size-off-sizeof(size_t));
119 if(!result)
120 printf("FAILED TO INSERT MEMORY POOL\n");
121};//{(void)mem_size;};
122
123#ifndef INCLUDED_tlsfbits
124//From tlsf internals
125typedef struct block_header_t
126{
127 /* Points to the previous physical block. */
129
130 /* The size of this block, excluding the block header. */
131 size_t size;
132
133 /* Next and previous free blocks. */
137static const size_t block_header_free_bit = 1 << 0;
138#endif
139
141 // TODO: log about unsupported nested transaction when a RT compliant
142 // logging is available and transaction_active == true
143 transaction_active = true;
145}
146
148 // TODO: log about invalid end of transaction when a RT copmliant logging
149 // is available and transaction_active == false
150 transaction_active = false;
151}
152
153bool Allocator::memFree(void *pool) const
154{
155 size_t bh_shift = sizeof(next_t)+sizeof(size_t);
156 //Assume that memory is free to start with
157 bool isFree = true;
158 //Get the block header from the pool
159 block_header_t &bh = *(block_header_t*)((char*)pool+bh_shift);
160 //The first block must be free
161 if((bh.size&block_header_free_bit) == 0)
162 isFree = false;
164 (((char*)&bh)+((bh.size&~0x3)+bh_shift-2*sizeof(size_t)));
165 //The next block must be 'non-free' and zero length
166 if((bhn.size&block_header_free_bit) != 0)
167 isFree = false;
168 if((bhn.size&~0x3) != 0)
169 isFree = false;
170
171 return isFree;
172}
173
175{
176 int i = 1;
177 next_t *n = impl->pools;
178 while(n->next) {
179 i++;
180 n = n->next;
181 }
182 return i;
183}
184
186{
187 int i = 0;
188 next_t *n = impl->pools->next;
189 while(n) {
190 if(memFree(n))
191 i++;
192 n = n->next;
193 }
194 return i;
195}
196
197
198unsigned long long Allocator::totalAlloced() const
199{
200 return impl->totalAlloced;
201}
202
204
205 // if a transaction is active
206 if (transaction_active) {
207
208 // deallocate all allocated memory within this transaction
209 for (size_t temp_idx = 0;
210 temp_idx < transaction_alloc_index; ++temp_idx) {
212 }
213
214 }
215
216 transaction_active = false;
217}
218
219/*
220 * Notes on tlsf internals
221 * - TLSF consists of blocks linked by block headers and these form a doubly
222 * linked list of free segments
223 * - Original memory is [control_t pool]
224 * base sentinal
225 * Pools are [block_t block_t blocks ...]
226 * Blocks are [memory block_t](??)
227 * - These are stored in the control_t structure in an order dependent on the
228 * size that they are
229 * it's a bit unclear how collisions are handled here, but the basic premise
230 * makes sense
231 * - Additional structure is added before the start of each pool to define the
232 * pool size and the next pool in the list as this information is not
233 * accessible in O(good) time
234 */
235
236}
pool_t pool
Definition Util.cpp:167
bool lowMemory(unsigned n, size_t chunk_size) const
Definition Allocator.cpp:89
void dealloc_mem(void *memory)
Definition Allocator.cpp:82
void addMemory(void *, size_t mem_size)
Definition Allocator.cpp:106
void * alloc_mem(size_t mem_size)
Definition Allocator.cpp:73
unsigned long long totalAlloced() const
Definition Allocator.cpp:198
void endTransaction()
Definition Allocator.cpp:147
int memPools() const
Definition Allocator.cpp:174
bool memFree(void *pool) const
Definition Allocator.cpp:153
virtual ~Allocator(void)
Definition Allocator.cpp:62
bool transaction_active
Definition Allocator.h:130
void rollbackTransaction()
Definition Allocator.cpp:203
virtual void dealloc_mem(void *memory)=0
struct AllocatorImpl * impl
Definition Allocator.h:123
void beginTransaction()
Definition Allocator.cpp:140
int freePools() const
Definition Allocator.cpp:185
size_t transaction_alloc_index
Definition Allocator.h:129
void * transaction_alloc_content[max_transaction_length]
Definition Allocator.h:128
Allocator(void)
Definition Allocator.cpp:49
the dummy allocator, which does not allow any allocation
Definition Allocator.h:165
unsigned v[N_MAX]
Definition inflate.c:1584
register unsigned i
Definition inflate.c:1575
JSAMPIMAGE data
Definition jpeglib.h:945
Definition zynaddsubfx-src.cpp:569
DummyAllocator DummyAlloc
Definition Allocator.cpp:23
static const size_t block_header_free_bit
Definition Allocator.cpp:137
Definition tlsf.c:111
Definition Allocator.cpp:39
unsigned long long totalAlloced
Definition Allocator.cpp:46
next_t * pools
Definition Allocator.cpp:45
void * tlsf
Definition Allocator.cpp:40
Definition Allocator.cpp:126
size_t size
Definition Allocator.cpp:131
struct block_header_t * prev_free
Definition Allocator.cpp:135
struct block_header_t * next_free
Definition Allocator.cpp:134
struct block_header_t * prev_phys_block
Definition Allocator.cpp:128
Definition Allocator.cpp:27
size_t pool_size
Definition Allocator.cpp:29
next_t * next
Definition Allocator.cpp:28
void tlsf_free(tlsf_t tlsf, void *ptr)
Definition tlsf.c:971
size_t tlsf_pool_overhead()
Definition tlsf.c:764
pool_t tlsf_add_pool(tlsf_t tlsf, void *mem, size_t bytes)
Definition tlsf.c:774
size_t tlsf_size()
Definition tlsf.c:739
tlsf_t tlsf_create_with_pool(void *mem, size_t bytes)
Definition tlsf.c:891
void * tlsf_malloc(tlsf_t tlsf, size_t size)
Definition tlsf.c:909
int n
Definition crypt.c:458
int result
Definition process.c:1455
char * malloc()