xref: /dflybsd-src/contrib/tre/lib/tre-mem.c (revision 071cbfc5b674dbc05e198747dddf53a507e3290a)
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