Lolly 1.4.27
Loading...
Searching...
No Matches
fast_alloc.cpp
Go to the documentation of this file.
1
2/******************************************************************************
3 * MODULE : Fast memory allocation
4 * DESCRIPTION: Fast allocations is realized by using a linked list
5 * of allocations for each fixed size divisible by
6 * a word legth up to MAX_FAST. Otherwise,
7 * usual memory allocation is used.
8 * ASSUMPTIONS: The word size of the computer is 4.
9 * Otherwise, change WORD_LENGTH.
10 * COPYRIGHT : (C) 1999 Joris van der Hoeven
11 *******************************************************************************
12 * This software falls under the GNU general public license version 3 or later.
13 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
14 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
15 ******************************************************************************/
16
17#include "fast_alloc.hpp"
18#include "tm_ostream.hpp"
19#include <cstring>
20
21/******************************************************************************
22 * Globals
23 ******************************************************************************/
24
25void* alloc_table[MAX_FAST]; // Static declaration initializes with NULL's
27#ifdef DEBUG_ON
28char* alloc_mem_top = NULL;
29char* alloc_mem_bottom= (char*) ((unsigned long long) -1);
30#endif
31size_t alloc_remains= 0;
32int allocated = 0;
34int large_uses = 0;
35int MEM_DEBUG = 0;
36
37/*****************************************************************************/
38// General purpose fast allocation routines
39/*****************************************************************************/
40
41#define alloc_ptr(i) alloc_table[i]
42#define ind(ptr) (*((void**) ptr))
43
44bool break_stub (void* ptr);
45int mem_used ();
46
47void*
48safe_malloc (size_t sz) {
49 void* ptr= malloc (sz);
50 if (ptr == NULL) {
51 cerr << "Fatal error: out of memory\n";
52 abort ();
53 }
54 return ptr;
55}
56
57void*
58enlarge_malloc (size_t sz) {
59 if (alloc_remains < sz) {
60 if (alloc_remains > 0) {
63 }
65#ifdef DEBUG_ON
71#endif
74 }
75 void* ptr= alloc_mem;
76 alloc_mem+= sz;
77 alloc_remains-= sz;
78 return ptr;
79}
80
81void*
82fast_alloc (size_t sz) {
83 sz= (sz + WORD_LENGTH_INC) & WORD_MASK;
84 if (sz < MAX_FAST) {
85 void* ptr= alloc_ptr (sz);
86 if (ptr == NULL) return enlarge_malloc (sz);
87 alloc_ptr (sz)= ind (ptr);
88#ifdef DEBUG_ON
90#endif
91 return ptr;
92 }
93 else {
94 if (MEM_DEBUG >= 3) cout << "Big alloc of " << sz << " bytes\n";
95 if (MEM_DEBUG >= 3) cout << "Memory used: " << mem_used () << " bytes\n";
96 large_uses+= sz;
97 return safe_malloc (sz);
98 }
99}
100
101void
102fast_free (void* ptr, size_t sz) {
103 sz= (sz + WORD_LENGTH_INC) & WORD_MASK;
104 if (sz < MAX_FAST) {
105#ifdef DEBUG_ON
106 break_stub (ptr);
107 break_stub (alloc_ptr (sz));
108#endif
109 ind (ptr) = alloc_ptr (sz);
110 alloc_ptr (sz)= ptr;
111 }
112 else {
113 if (MEM_DEBUG >= 3) cout << "Big free of " << sz << " bytes\n";
114 large_uses-= sz;
115 free (ptr);
116 if (MEM_DEBUG >= 3) cout << "Memory used: " << mem_used () << " bytes\n";
117 }
118}
119
120void*
121fast_realloc (void* ptr, size_t old_size, size_t new_size) {
125 if (MEM_DEBUG >= 3)
126 cout << "Big realloc from " << old_size << " to " << new_size
127 << " bytes\n";
129 if (MEM_DEBUG >= 3) cout << "Memory used: " << mem_used () << " bytes\n";
130 return realloc (ptr, new_size);
131 }
132 else {
133 void* newptr= fast_alloc (new_size);
136 return newptr;
137 }
138}
139
140void*
141fast_new (size_t s) {
142 void* ptr;
143#ifdef DEBUG_ON
144 s= (s + (4 * WORD_LENGTH) + WORD_LENGTH_INC) & WORD_MASK;
145#else
147#endif
148 if (s < MAX_FAST) {
149 ptr= alloc_ptr (s);
150 if (ptr == NULL) ptr= enlarge_malloc (s);
151 else alloc_ptr (s)= ind (ptr);
152#ifdef DEBUG_ON
153 break_stub (ptr);
154#endif
155 }
156 else {
157 if (MEM_DEBUG >= 3) cout << "Big alloc of " << s << " bytes\n";
158 if (MEM_DEBUG >= 3) cout << "Memory used: " << mem_used () << " bytes\n";
159 ptr= safe_malloc (s);
160 // if ((((int) ptr) & 15) != 0) cout << "Unaligned new " << ptr << "\n";
161 large_uses+= s;
162 }
163#ifdef DEBUG_ON
164 char* mem = (char*) ptr;
165 *((size_t*) ptr) = s;
166 ptr = ((char*) ptr) + WORD_LENGTH;
167 *((size_t*) ptr) = s;
168 ptr = ((char*) ptr) + WORD_LENGTH;
169 *((size_t*) ptr) = ~s;
170 ptr = ((char*) ptr) + WORD_LENGTH;
171 *((int*) (mem + s - WORD_LENGTH))= 0x55aa;
172 return (void*) ptr;
173#else
174 *((size_t*) ptr)= s;
175 return (void*) (((char*) ptr) + WORD_LENGTH);
176#endif
177}
178
179#ifdef DEBUG_ON
180void*
181alloc_check (const char* msg, void* ptr, size_t* sp) {
182 void* mem = ptr;
183 ptr = (void*) (((char*) ptr) - WORD_LENGTH);
184 size_t comp= *((size_t*) ptr);
185 ptr = (void*) (((char*) ptr) - WORD_LENGTH);
186 size_t s1 = *((size_t*) ptr);
187 ptr = (void*) (((char*) ptr) - WORD_LENGTH);
188 size_t s = *((size_t*) ptr);
189 if ((s1 + comp) != -1 || (s + comp) != -1) {
190 printf ("%s %p size mismatch at %p %lu:%lu :%lu:%lu\n", msg, mem, ptr, s,
191 s + comp, s1, s1 + comp);
192 if (break_stub (ptr)) s= s1 < s ? s1 : s;
193 } // else printf("fast_delete %p size %lu at %p\n",mem,s,ptr);
194 if (*((int*) ((char*) ptr + s - WORD_LENGTH)) != 0x55AA) {
195 printf ("%s buffer overflow %x\n", msg, *((int*) ((char*) ptr + s - 1)));
196 }
197 if (sp) *sp= s;
198 return (ptr);
199}
200#endif
201
202void
204#ifdef DEBUG_ON
205 size_t s;
206 ptr= alloc_check ("fast_delete", ptr, &s);
207#else
208 ptr = (void*) (((char*) ptr) - WORD_LENGTH);
209 size_t s= *((size_t*) ptr);
210#endif
211 if (s < MAX_FAST) {
212#ifdef DEBUG_ON
213 break_stub (ptr);
214 break_stub (alloc_ptr (s));
215#endif
216 ind (ptr) = alloc_ptr (s);
217 alloc_ptr (s)= ptr;
218 }
219 else {
220 if (MEM_DEBUG >= 3) cout << "Big free of " << s << " bytes\n";
221 // if ((((int) ptr) & 15) != 0) cout << "Unaligned delete " << ptr << "\n";
222 free (ptr);
223 large_uses-= s;
224 if (MEM_DEBUG >= 3) cout << "Memory used: " << mem_used () << " bytes\n";
225 }
226}
227
228/******************************************************************************
229 * Fast allocation of blocks whose sizes are small multiples of WORD_LENGTH
230 ******************************************************************************/
231
232void*
233fast_alloc_mw (size_t s) {
234 if (s < MAX_FAST) {
235 void* ptr= alloc_ptr (s);
236 if (ptr == NULL) return enlarge_malloc (s);
237 alloc_ptr (s)= ind (ptr);
238 return ptr;
239 }
240 else return safe_malloc (s);
241}
242
243void
244fast_free_mw (void* ptr, size_t s) {
245 if (s < MAX_FAST) {
246 ind (ptr) = alloc_ptr (s);
247 alloc_ptr (s)= ptr;
248 }
249 else free (ptr);
250}
251
252/******************************************************************************
253 * Statistics
254 ******************************************************************************/
255
256int
258 int i= -1;
259 while (ptr != NULL) {
260 i++;
261 ptr= ind (ptr);
262 }
263 return i;
264}
265
266int
270 int i;
271 for (i= WORD_LENGTH; i < MAX_FAST; i+= WORD_LENGTH)
274 return small_uses + large_uses;
275}
276
277void
279 cout << "\n---------------- memory statistics ----------------\n";
282 int i;
283 for (i= WORD_LENGTH; i < MAX_FAST; i+= WORD_LENGTH)
287 // cout << "Fast chunks : " << chunks_use << " bytes\n";
288 // cout << "Free on chunks: " << alloc_remains << " bytes\n";
289 cout << "User : " << total_uses << " bytes\n";
290 cout << "Allocator : " << chunks_use + large_uses << " bytes\n";
291 cout << "Small mallocs : "
292 << ((100 * ((float) small_uses)) / ((float) total_uses)) << "%\n";
293}
294
295#ifdef DEBUG_ON
296bool
297break_stub (void* ptr) {
298 if (ptr && (ptr > (void*) alloc_mem_top || ptr < (void*) alloc_mem_bottom)) {
299 printf ("Bad pointer in fast_alloc:%p %p:%p\n", ptr, alloc_mem_bottom,
301 return true;
302 }
303 return false;
304}
305#endif
306
307void
309
310/******************************************************************************
311 * Redefine standard new and delete
312 ******************************************************************************/
313
314#if defined(X11TEXMACS) && (!defined(NO_FAST_ALLOC))
315
316void*
317operator new (size_t s) {
318 void* ptr;
320 if (s < MAX_FAST) {
321 ptr= alloc_ptr (s);
322 if (ptr == NULL) ptr= enlarge_malloc (s);
323 else alloc_ptr (s)= ind (ptr);
324 }
325 else {
326 ptr= safe_malloc (s);
327 large_uses+= s;
328 }
329 *((size_t*) ptr)= s;
330 return (void*) (((char*) ptr) + WORD_LENGTH);
331}
332
333void
334operator delete (void* ptr) {
335 ptr = (void*) (((char*) ptr) - WORD_LENGTH);
336 size_t s= *((size_t*) ptr);
337 if (s < MAX_FAST) {
338 ind (ptr) = alloc_ptr (s);
339 alloc_ptr (s)= ptr;
340 }
341 else {
342 free (ptr);
343 large_uses-= s;
344 }
345}
346
347void*
348operator new[] (size_t s) {
349 void* ptr;
351 if (s < MAX_FAST) {
352 ptr= alloc_ptr (s);
353 if (ptr == NULL) ptr= enlarge_malloc (s);
354 else alloc_ptr (s)= ind (ptr);
355 }
356 else {
357 ptr= safe_malloc (s);
358 large_uses+= s;
359 }
360 *((size_t*) ptr)= s;
361 return (void*) (((char*) ptr) + WORD_LENGTH);
362}
363
364void
365operator delete[] (void* ptr) {
366 ptr = (void*) (((char*) ptr) - WORD_LENGTH);
367 size_t s= *((size_t*) ptr);
368 if (s < MAX_FAST) {
369 ind (ptr) = alloc_ptr (s);
370 alloc_ptr (s)= ptr;
371 }
372 else {
373 free (ptr);
374 large_uses-= s;
375 }
376}
377
378#endif // defined(X11TEXMACS) && (!defined(NO_FAST_ALLOC))
The list class represents a linked list.
Definition list.hpp:48
void * fast_realloc(void *ptr, size_t old_size, size_t new_size)
bool break_stub(void *ptr)
int allocated
void mem_info()
void fast_delete(void *ptr)
void fast_free(void *ptr, size_t sz)
void * alloc_table[MAX_FAST]
int large_uses
char * alloc_mem
void fast_free_mw(void *ptr, size_t s)
#define ind(ptr)
int fast_chunks
size_t alloc_remains
void * fast_alloc_mw(size_t s)
int mem_used()
void * fast_new(size_t s)
#define alloc_ptr(i)
void * fast_alloc(size_t sz)
void mem_init()
int MEM_DEBUG
void * safe_malloc(size_t sz)
int compute_free(void *ptr)
void * enlarge_malloc(size_t sz)
#define WORD_LENGTH
#define WORD_LENGTH_INC
#define MAX_FAST
#define WORD_MASK
#define BLOCK_SIZE
void * alloc_check(const char *msg, void *ptr, size_t *sp)
tm_ostream & cerr
tm_ostream & cout