Merge remote-tracking branch 'leaf/vendor/GDB'
[dragonfly.git] / contrib / tre / lib / tre-mem.c
1 /*
2   tre-mem.c - TRE memory allocator
3
4   This software is released under a BSD-style license.
5   See the file LICENSE for details and copyright.
6
7 */
8
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.
14 */
15
16 #ifdef HAVE_CONFIG_H
17 #include <config.h>
18 #endif /* HAVE_CONFIG_H */
19 #include <stdlib.h>
20 #include <string.h>
21
22 #include "tre-internal.h"
23 #include "tre-mem.h"
24 #include "xmalloc.h"
25
26
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)
30 {
31   tre_mem_t mem;
32   if (provided)
33     {
34       mem = provided_block;
35       memset(mem, 0, sizeof(*mem));
36     }
37   else
38     mem = xcalloc(1, sizeof(*mem));
39   if (mem == NULL)
40     return NULL;
41   return mem;
42 }
43
44
45 /* Frees the memory allocator and all memory allocated with it. */
46 void
47 tre_mem_destroy(tre_mem_t mem)
48 {
49   tre_list_t *tmp, *l = mem->blocks;
50
51   while (l != NULL)
52     {
53       xfree(l->data);
54       tmp = l->next;
55       xfree(l);
56       l = tmp;
57     }
58   xfree(mem);
59 }
60
61
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)
67 {
68   void *ptr;
69
70   if (mem->failed)
71     {
72       DPRINT(("tre_mem_alloc: oops, called after failure?!\n"));
73       return NULL;
74     }
75
76 #ifdef MALLOC_DEBUGGING
77   if (!provided)
78     {
79       ptr = xmalloc(1);
80       if (ptr == NULL)
81         {
82           DPRINT(("tre_mem_alloc: xmalloc forced failure\n"));
83           mem->failed = 1;
84           return NULL;
85         }
86       xfree(ptr);
87     }
88 #endif /* MALLOC_DEBUGGING */
89
90   if (mem->n < size)
91     {
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)
96         {
97           DPRINT(("tre_mem_alloc: using provided block\n"));
98           if (provided_block == NULL)
99             {
100               DPRINT(("tre_mem_alloc: provided block was NULL\n"));
101               mem->failed = 1;
102               return NULL;
103             }
104           mem->ptr = provided_block;
105           mem->n = TRE_MEM_BLOCK_SIZE;
106         }
107       else
108         {
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)
118             {
119               mem->failed = 1;
120               return NULL;
121             }
122           l->data = xmalloc(block_size);
123           if (l->data == NULL)
124             {
125               xfree(l);
126               mem->failed = 1;
127               return NULL;
128             }
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;
137         }
138     }
139
140   /* Make sure the next pointer will be aligned. */
141   size += ALIGN(mem->ptr + size, long);
142
143   /* Allocate from current block. */
144   ptr = mem->ptr;
145   mem->ptr += size;
146   mem->n -= size;
147
148   /* Set to zero if needed. */
149   if (zero)
150     memset(ptr, 0, size);
151
152   return ptr;
153 }
154
155 /* EOF */