tre-mem.c revision 1.1 1 1.1 agc /*
2 1.1 agc tre-mem.c - TRE memory allocator
3 1.1 agc
4 1.1 agc This software is released under a BSD-style license.
5 1.1 agc See the file LICENSE for details and copyright.
6 1.1 agc
7 1.1 agc */
8 1.1 agc
9 1.1 agc /*
10 1.1 agc This memory allocator is for allocating small memory blocks efficiently
11 1.1 agc in terms of memory overhead and execution speed. The allocated blocks
12 1.1 agc cannot be freed individually, only all at once. There can be multiple
13 1.1 agc allocators, though.
14 1.1 agc */
15 1.1 agc
16 1.1 agc #ifdef HAVE_CONFIG_H
17 1.1 agc #include <config.h>
18 1.1 agc #endif /* HAVE_CONFIG_H */
19 1.1 agc #include <stdlib.h>
20 1.1 agc #include <string.h>
21 1.1 agc
22 1.1 agc #include "tre-internal.h"
23 1.1 agc #include "tre-mem.h"
24 1.1 agc #include "xmalloc.h"
25 1.1 agc
26 1.1 agc
27 1.1 agc /* Returns a new memory allocator or NULL if out of memory. */
28 1.1 agc tre_mem_t
29 1.1 agc tre_mem_new_impl(int provided, void *provided_block)
30 1.1 agc {
31 1.1 agc tre_mem_t mem;
32 1.1 agc if (provided)
33 1.1 agc {
34 1.1 agc mem = provided_block;
35 1.1 agc memset(mem, 0, sizeof(*mem));
36 1.1 agc }
37 1.1 agc else
38 1.1 agc mem = xcalloc(1, sizeof(*mem));
39 1.1 agc if (mem == NULL)
40 1.1 agc return NULL;
41 1.1 agc return mem;
42 1.1 agc }
43 1.1 agc
44 1.1 agc
45 1.1 agc /* Frees the memory allocator and all memory allocated with it. */
46 1.1 agc void
47 1.1 agc tre_mem_destroy(tre_mem_t mem)
48 1.1 agc {
49 1.1 agc tre_list_t *tmp, *l = mem->blocks;
50 1.1 agc
51 1.1 agc while (l != NULL)
52 1.1 agc {
53 1.1 agc xfree(l->data);
54 1.1 agc tmp = l->next;
55 1.1 agc xfree(l);
56 1.1 agc l = tmp;
57 1.1 agc }
58 1.1 agc xfree(mem);
59 1.1 agc }
60 1.1 agc
61 1.1 agc
62 1.1 agc /* Allocates a block of `size' bytes from `mem'. Returns a pointer to the
63 1.1 agc allocated block or NULL if an underlying malloc() failed. */
64 1.1 agc void *
65 1.1 agc tre_mem_alloc_impl(tre_mem_t mem, int provided, void *provided_block,
66 1.1 agc int zero, size_t size)
67 1.1 agc {
68 1.1 agc void *ptr;
69 1.1 agc
70 1.1 agc if (mem->failed)
71 1.1 agc {
72 1.1 agc DPRINT(("tre_mem_alloc: oops, called after failure?!\n"));
73 1.1 agc return NULL;
74 1.1 agc }
75 1.1 agc
76 1.1 agc #ifdef MALLOC_DEBUGGING
77 1.1 agc if (!provided)
78 1.1 agc {
79 1.1 agc ptr = xmalloc(1);
80 1.1 agc if (ptr == NULL)
81 1.1 agc {
82 1.1 agc DPRINT(("tre_mem_alloc: xmalloc forced failure\n"));
83 1.1 agc mem->failed = 1;
84 1.1 agc return NULL;
85 1.1 agc }
86 1.1 agc xfree(ptr);
87 1.1 agc }
88 1.1 agc #endif /* MALLOC_DEBUGGING */
89 1.1 agc
90 1.1 agc if (mem->n < size)
91 1.1 agc {
92 1.1 agc /* We need more memory than is available in the current block.
93 1.1 agc Allocate a new block. */
94 1.1 agc tre_list_t *l;
95 1.1 agc if (provided)
96 1.1 agc {
97 1.1 agc DPRINT(("tre_mem_alloc: using provided block\n"));
98 1.1 agc if (provided_block == NULL)
99 1.1 agc {
100 1.1 agc DPRINT(("tre_mem_alloc: provided block was NULL\n"));
101 1.1 agc mem->failed = 1;
102 1.1 agc return NULL;
103 1.1 agc }
104 1.1 agc mem->ptr = provided_block;
105 1.1 agc mem->n = TRE_MEM_BLOCK_SIZE;
106 1.1 agc }
107 1.1 agc else
108 1.1 agc {
109 1.1 agc int block_size;
110 1.1 agc if (size * 8 > TRE_MEM_BLOCK_SIZE)
111 1.1 agc block_size = size * 8;
112 1.1 agc else
113 1.1 agc block_size = TRE_MEM_BLOCK_SIZE;
114 1.1 agc DPRINT(("tre_mem_alloc: allocating new %d byte block\n",
115 1.1 agc block_size));
116 1.1 agc l = xmalloc(sizeof(*l));
117 1.1 agc if (l == NULL)
118 1.1 agc {
119 1.1 agc mem->failed = 1;
120 1.1 agc return NULL;
121 1.1 agc }
122 1.1 agc l->data = xmalloc(block_size);
123 1.1 agc if (l->data == NULL)
124 1.1 agc {
125 1.1 agc xfree(l);
126 1.1 agc mem->failed = 1;
127 1.1 agc return NULL;
128 1.1 agc }
129 1.1 agc l->next = NULL;
130 1.1 agc if (mem->current != NULL)
131 1.1 agc mem->current->next = l;
132 1.1 agc if (mem->blocks == NULL)
133 1.1 agc mem->blocks = l;
134 1.1 agc mem->current = l;
135 1.1 agc mem->ptr = l->data;
136 1.1 agc mem->n = block_size;
137 1.1 agc }
138 1.1 agc }
139 1.1 agc
140 1.1 agc /* Make sure the next pointer will be aligned. */
141 1.1 agc size += ALIGN(mem->ptr + size, long);
142 1.1 agc
143 1.1 agc /* Allocate from current block. */
144 1.1 agc ptr = mem->ptr;
145 1.1 agc mem->ptr += size;
146 1.1 agc mem->n -= size;
147 1.1 agc
148 1.1 agc /* Set to zero if needed. */
149 1.1 agc if (zero)
150 1.1 agc memset(ptr, 0, size);
151 1.1 agc
152 1.1 agc return ptr;
153 1.1 agc }
154 1.1 agc
155 1.1 agc /* EOF */
156