sys/vfs/hammer2: Fix multiple "radii" -> "radix"
[dragonfly.git] / contrib / tre / lib / tre-mem.c
blobb5fb2768d292a26b2ec3a9ab1669e59e9bb785b0
1 /*
2 tre-mem.c - TRE memory allocator
4 This software is released under a BSD-style license.
5 See the file LICENSE for details and copyright.
7 */
9 /*
10 This memory allocator is for allocating small memory blocks efficiently
11 in terms of memory overhead and execution speed. The allocated blocks
12 cannot be freed individually, only all at once. There can be multiple
13 allocators, though.
16 #ifdef HAVE_CONFIG_H
17 #include <config.h>
18 #endif /* HAVE_CONFIG_H */
19 #include <stdlib.h>
20 #include <string.h>
22 #include "tre-internal.h"
23 #include "tre-mem.h"
24 #include "xmalloc.h"
27 /* Returns a new memory allocator or NULL if out of memory. */
28 tre_mem_t
29 tre_mem_new_impl(int provided, void *provided_block)
31 tre_mem_t mem;
32 if (provided)
34 mem = provided_block;
35 memset(mem, 0, sizeof(*mem));
37 else
38 mem = xcalloc(1, sizeof(*mem));
39 if (mem == NULL)
40 return NULL;
41 return mem;
45 /* Frees the memory allocator and all memory allocated with it. */
46 void
47 tre_mem_destroy(tre_mem_t mem)
49 tre_list_t *tmp, *l = mem->blocks;
51 while (l != NULL)
53 xfree(l->data);
54 tmp = l->next;
55 xfree(l);
56 l = tmp;
58 xfree(mem);
62 /* Allocates a block of `size' bytes from `mem'. Returns a pointer to the
63 allocated block or NULL if an underlying malloc() failed. */
64 void *
65 tre_mem_alloc_impl(tre_mem_t mem, int provided, void *provided_block,
66 int zero, size_t size)
68 void *ptr;
70 if (mem->failed)
72 DPRINT(("tre_mem_alloc: oops, called after failure?!\n"));
73 return NULL;
76 #ifdef MALLOC_DEBUGGING
77 if (!provided)
79 ptr = xmalloc(1);
80 if (ptr == NULL)
82 DPRINT(("tre_mem_alloc: xmalloc forced failure\n"));
83 mem->failed = 1;
84 return NULL;
86 xfree(ptr);
88 #endif /* MALLOC_DEBUGGING */
90 if (mem->n < size)
92 /* We need more memory than is available in the current block.
93 Allocate a new block. */
94 tre_list_t *l;
95 if (provided)
97 DPRINT(("tre_mem_alloc: using provided block\n"));
98 if (provided_block == NULL)
100 DPRINT(("tre_mem_alloc: provided block was NULL\n"));
101 mem->failed = 1;
102 return NULL;
104 mem->ptr = provided_block;
105 mem->n = TRE_MEM_BLOCK_SIZE;
107 else
109 int block_size;
110 if (size * 8 > TRE_MEM_BLOCK_SIZE)
111 block_size = size * 8;
112 else
113 block_size = TRE_MEM_BLOCK_SIZE;
114 DPRINT(("tre_mem_alloc: allocating new %d byte block\n",
115 block_size));
116 l = xmalloc(sizeof(*l));
117 if (l == NULL)
119 mem->failed = 1;
120 return NULL;
122 l->data = xmalloc(block_size);
123 if (l->data == NULL)
125 xfree(l);
126 mem->failed = 1;
127 return NULL;
129 l->next = NULL;
130 if (mem->current != NULL)
131 mem->current->next = l;
132 if (mem->blocks == NULL)
133 mem->blocks = l;
134 mem->current = l;
135 mem->ptr = l->data;
136 mem->n = block_size;
140 /* Make sure the next pointer will be aligned. */
141 size += ALIGN(mem->ptr + size, long);
143 /* Allocate from current block. */
144 ptr = mem->ptr;
145 mem->ptr += size;
146 mem->n -= size;
148 /* Set to zero if needed. */
149 if (zero)
150 memset(ptr, 0, size);
152 return ptr;
155 /* EOF */