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